sed 删除模式后的行并在此间隔中添加新行

sed 删除模式后的行并在此间隔中添加新行

我试图自动更新一些文件。我需要找到一行并删除该行之后的一些行;我还需要用替换行代替已删除的行。

举个例子会更清楚。

原来的:

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

所以我想:

  1. 搜索模式,例如bb/bb/bb/bb,所以我们保留前两行;然后

  2. 删除并替换接下来的第 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。eded> /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不会失败。

相关内容