48. 删除多行中的第一行(D 命令)
正如我们之前讨论的,小写 d
命令删除当前模式空间,将下一行从输入文件读取到模式空间,中止其余的 sed 命令并再次开始循环。
大写的 D
命令删除后不会将下一行读取到模式空间,也不会完全清除模式缓冲区(除非只有一行)。相反,它执行以下操作:
- 删除部分模式空间,直到遇到换行符(
\n
)。 - 中止剩余的 sed 命令并从头开始对模式缓冲区中的剩余内容执行命令。
考虑以下文件,其中每个标题的注释都包含在 @
和 @
之间。
请注意,在某些情况下,此注释也会跨越界限。 例如 @Information Technology officer@
跨越两行。
创建以下示例文件。
$ vi empnametitle-with-comment.txt John Doe CEO @Chief Executive Officer@ Jason Smith IT Manager @Information Technology Officer@ Raj Reddy Sysadmin @System Administrator@ Anand Ram Developer @Senior Programmer@ Jane Miller Sales Manager @Sales Manager@
我们的目标是从此文件中删除这些注释。 这可以按如下所示完成。
$ sed -e '/@/{N;/@.*@/{s/@.*@//;P;D}}' empnametitle-with-comment.txt John Doe CEO Jason Smith IT Manager Raj Reddy Sysadmin Anand Ram Developer Jane Miller Sales Manager
您还可以将其保存在 sed 脚本文件中并执行它,如下所示。
$ vi D-upper.sed #!/bin/sed -f /@/ { N /@.*@/ {s/@.*@//;P;D } } $ chmod u+x D-upper.sed $ ./D-upper.sed empnametitle-with-comment.txt
在上面的例子中:
/@/ {
—— 这是外循环。 sed 查找任何包含@
符号的行。 如果找到一个,它就会执行其余的逻辑。如果没有,它会读取下一行。 例如,让我们以第 4 行为例,它是"@Information Technology"
(注释跨越多个列,也转到第 5 行)。第 4 行有一个@
符号,因此执行其余命令。N
—— 从输入文件中获取下一行并将其附加到模式空间。 例如,这将读取第 5 行"Officer@"
,并将其附加到模式空间。 因此,模式空间将包含"@Information Technology\nOfficer@"
。/@.*@/
—— 搜索模式空间是否具有模式"@.*@"
,这意味着@
和@
之间包含的任何内容。该表达式对于当前模式空间成立,因此进入下一步。s/@.*@//;P;D
—— 这将替换整个文本"@Information Technology\nOfficer@"
(基本上它会删除该文本)。P
打印该行的第一部分。D
删除模式空间的其余内容。逻辑又从上往下继续。