本文共 5326 字,大约阅读时间需要 17 分钟。
Consult Section 3.1 in the Owner and OperatorGuide for a description of the tape drivesavailable on your system.我们用N命令试下手:
$ sed '/Operator$/{N;s/Owner and Operator\nGuide/Installation Guide/}' textConsult Section 3.1 in the Installation Guide for a description of the tape drivesavailable on your system.不过这个例子有两个局限:
$ sed '/Operator$/{N;s/Owner and Operator\nGuide /Installation Guide\n/}' textConsult Section 3.1 in the Installation Guidefor a description of the tape drivesavailable on your system.现在去掉第1个前提,我们引入更加复杂的测试文本,这段文本中Owner and Operator Guide有位于一行的,也有跨越多行的情况:
$ cat textConsult Section 3.1 in the Owner and OperatorGuide for a description of the tape drivesavailable on your system.Look in the Owner and Operator Guide shipped with your system.Two manuals are provided including the Owner andOperator Guide and the User Guide.The Owner and Operator Guide is shipped with your system.相应地修改下之前执行的命令,如下所示:
$ sed 's/Owner and Operator Guide/Installation Guide//Owner/{Ns/ *\n/ /s/Owner and Operator Guide */Installation Guide\/}' textConsult Section 3.1 in the Installation Guidefor a description of the tape drivesavailable on your system.Look in the Installation Guide shipped with your system.Two manuals are provided including the Installation Guideand the User Guide.The Installation Guide is shipped with your system.这里我们首先将在单行出现的Owner and Operator Guide替换为Installation Guide,然后再寻找匹配Owner的行,匹配后读取下一行的内容到模式空间,并且将中间的换行符替换成空格,最后再替换Owner and Operator Guide。 解释起来很简单,但是中间还是有些门道的。比如你可能觉得这里最前面的s/Owner and Operator Guide/Installation Guide/命令是多余的,假设你删除这一句:
$ sed '/Owner/{> N> s/ *\n/ /> s/Owner and Operator Guide */Installation Guide\> /> }' textConsult Section 3.1 in the Installation Guidefor a description of the tape drivesavailable on your system.Look in the Installation Guideshipped with your system. Two manuals are provided including the Installation Guideand the User Guide.The Owner and Operator Guide is shipped with your system.最明显的问题是最后一行没有被替换,原因是当最后一行的被读入到模式空间后,匹配Owner,执行N命令读入下一行,但是因为当前已经是最后一行,所以N读取替换,告诉sed可以退出了,sed也不会继续执行接下来的替换命令( 注:书中说最后一行不会被打印输出,我这边测试是会输出的)。所以这里需要在使用N的时候加一个判断,即当前行为最后一行时,不读取下一行的内容:$!N,这一点在很多场合都是有用的,更改后重新执行:
$ sed '/Owner/{> $!N> s/ *\n/ /> s/Owner and Operator Guide */Installation Guide\> /> }' textConsult Section 3.1 in the Installation Guidefor a description of the tape drivesavailable on your system.Look in the Installation Guideshipped with your system. Two manuals are provided including the Installation Guideand the User Guide.The Installation Guideis shipped with your system.上面只是为了用例子说明N的用法,可能解决方案未必是最好的。
$ cat textThis line is followed by 1 blank line.This line is followed by 2 blank lines.This line is followed by 3 blank lines.This line is followed by 4 blank lines.This is the end.现在我们要删除多余的空行,将多个空行缩减成一行。假如我们使用d命令来删除,很简单的逻辑:
$ sed '/^$/{N;/^\n$/d}' textThis line is followed by 1 blank line.This line is followed by 2 blank lines.This line is followed by 3 blank lines.This line is followed by 4 blank lines.This is the end.我们会发现一个奇怪的结果,奇数个数的相连空行已经被合并成一行,但是偶数个数的却全部被删除了。造成这样的原因需要重新翻译下上面的命令,当匹配一个空行是,将下一行也读取到模式空间,然后若下一行也是空行,则模式空间中的内容应该是\n,因此匹配^\n$,从而执行d命令会将模式空间中的内容清空,结果就是相连的两个空行都被删除。这样就可以理解为什么相连奇数个空行的情况下是正常的,而偶数个数就有问题了。 这种情况下,我们就应该用D命令来处理,这样做就得到预期的结果了:
$ sed '/^$/{N;/^\n$/D}' textThis line is followed by 1 blank line.This line is followed by 2 blank lines.This line is followed by 3 blank lines.This line is followed by 4 blank lines.This is the end.D命令只会删除模式空间的第一行,而且删除后会重新在模式空间的内容上执行编辑命令,类似形成一个循环,前提是相连的都是空行。当匹配一个空行时,N读取下一行内容,此时匹配^\n$导致模式空间中的第一行被删除。现在模式空间中的内容是空的,重新执行编辑命令,此时匹配/^$/。继续读取下一行,当下一行依然为空行时,重复之前的动作,否则输出当前模式空间的内容。造成的结果是连续多个空行,只有最后一个空行是保留输出的,其余的都被删除了。这样的结果才是我们最初希望得到的。
$ echo -e "line1\nline2\nline3" | sed '$!N;P;D'不过多行命令用起来要格外小心,你要用自己的大脑去演算一遍执行的过程,要不然很容易出错,比如:
$ echo -e "line1\nline2\nline3" | sed -n 'N;1P'你可能期望打印第一行的内容,事实上并没有输出。原因是当N继续读入第二行后,当前行号已经是2了,我们在 笔记中曾经说过,行号只是sed在内部维护的一个计数变量而已,每当读入新的一行,行号就加一:
$ echo -e "line1\nline2\nline3" | sed -n '$!N;='23我们依然用替换Unix System为Unix Operating System作为例子,介绍N/P/D三个命令是如何配合使用的。 示例文本如下所示,为了举例方便,这段文本仅有三行内容,刚好可以演示一个循环的处理过程:
$ cat textThe UNIXSystem and UNIX...执行的命令:
$ sed '/UNIX$/{> N> s/\nSystem/ Operating &/> P> D> }' textThe UNIX Operating System and UNIX...执行过程如下图所示: 以上三个命令的用法与之前介绍的基础命令是截然不同的,有些同学可能都没有接触过。在下一篇中,我会介绍更多高级的命令,同时为引入一个新的概念:保持空间(Hold Space)。
转载地址:http://pldxx.baihongyu.com/