我试图自动更新一些文件。我需要找到一行并删除该行之后的一些行;我还需要用替换行代替已删除的行。
举个例子会更清楚。
原来的:
line aa/aa/aa/aa
line bb/bb/bb/bb
line cc/cc/cc/cc
line dd/dd/dd/dd
line ee/ee/ee/ee
line ff/ff/ff/ff
line gg/gg/gg/gg
line hh/hh/hh/hh
line ii/ii/ii/ii
所以我想:
搜索模式,例如
bb/bb/bb/bb
,所以我们保留前两行;然后删除并替换接下来的第 3 到第 6 行
uu/uu/uu/uu
最后结果:
line aa/aa/aa/aa
line bb/bb/bb/bb
line cc/cc/cc/cc
line dd/dd/dd/dd
line uu/uu/uu/uu
line ii/ii/ii/ii
我可以通过以下方式找到并删除这些行:
sed -e '/pattern/{n;N;N;N;N;d}' file.txt
但我不知道如何同时添加新行。我也对包含一些/
.
答案1
作为通配符暗示,可编写脚本的编辑器使这变得更容易。要将模式后的第三行到第六行替换bb/bb/bb/bb
为单行line uu/uu/uu/uu
,您可以使用以下ed
管道:
printf '%s\n' '/bb\/bb\/bb\/bb' '+3,+6c' 'line uu/uu/uu/uu' '.' 'wq' | ed -s file.txt > /dev/null
在较高级别上,我们通过管道将换行符分隔的命令发送到ed
,其中我们指示静默编辑名为的文件file.txt
并将任何“标准输出”放入位桶中/dev/null
。该标志抑制读入字节数和写出字节数的-s
正常输出。还将打印匹配的行(本场景中的“bb”行),因此通过.我们可以删除该标志并重定向 stdout 和 stderr。ed
ed
> /dev/null
-s
命令ed
本身是:
/bb\/bb\/bb\/bb
-- 搜索包含 的行/bb/bb/bb/bb
,其中我们必须转义正斜杠,因为否则ed
认为我们正在尝试bb/bb/bb
向匹配的行发送一个奇怪的命令/bb/
,因为前斜杠是一个语法字符。+3,+6c
-- 从这一行开始,c
将第 3 行到第 6 行挂在后面......line uu/uu/uu/uu
-- 到这一行.
-- 并告知ed
我们已完成更换线路wq
-- 然后w
将文件写入磁盘并q
安装ed
请注意,这假设bb/bb/bb/bb
出现在文件中;否则,当您尝试告诉ed
在文件末尾后编辑第三行到第六行时,您最终会遇到错误。如果您不能保证该模式存在于文件中,您可以在此脚本之前添加 agrep -q bb/bb/bb/bb file.txt && printf...
以有条件地执行管道。
答案2
和GNU sed
:
sed -ne '\#bb/bb/bb/bb#{p;n;p;n;p;n;n;n;n;a line uu/uu/uu/uu' -e ';b };p' file.txt
输出:
line aa/aa/aa/aa
line bb/bb/bb/bb
line cc/cc/cc/cc
line dd/dd/dd/dd
line uu/uu/uu/uu
line ii/ii/ii/ii
将输出保存到文件.txt改成。-ne
-ine
注意:代码中带有两个开关的间隙-e
是因为间隙告诉a
待定命令在哪里停止追加。
另一种方法是使用POSIX sed
,但这不是一句简单的话:
sed -n '\#bb/bb/bb/bb#{p;n;p;n;p;n;n;n;n;a\
line uu/uu/uu/uu
b };p' file.txt
答案3
使用 POSIX sed
,您可以执行以下操作:
$ sed -e '
\:line bb/bb/bb/bb:!b
n;n;n
N;N;N
s:.*:line uu/uu/uu/uu:
' inp
打印完目标行及其后的两行后,我们在模式空间中累积接下来的三行,并用预期的行更改整个模式空间。当将模式空间取出到标准输出时,换行符由 sed 本身处理。
请注意,我们假设目标行之后有足够的行,这样就N
不会失败。