sed进阶

       sed编辑器的基础命令能满足大多数日常文本编辑需求。本章将会介绍sed编辑器提供的更多高级特性。这些功能你未必会经常用到,但当需要时,知道这些功能的存在以及如何使用肯定是件好事。

一.多行命令
       在使用sed编辑器的基础命令时,你可能注意到了一个局限。所有的sed编辑器命令都是针对单行数据执行操作的。在sed编辑器读取数据流时,它会基于换行符的位置将数据分成行。sed编辑器根据定义好的脚本命令一次处理一行数据,然后移到下一行重复这个过程。
       有时需要对跨多行的数据执行特定操作。如果要查找或替换一个短语,就更是如此了。
       举个例子,如果你正在数据中查找短语Linux System Administrators Group,它很有可能出现在两行中,每行各包含其中一部分短语。如果用普通的sed编辑器命令来处理文本,就不可能发现这种被分开的短语。
       幸运的是,sed编辑器的设计人员已经考虑到了这种情况,并设计了对应的解决方案。sed编辑器包含了三个可用来处理多行文本的特殊命令。
        N:将数据流中的下一行加进来创建一个多行组(multiline group)来处理。
        D:删除多行组中的一行。
        P:打印多行组中的一行。

1.next命令
       在讲解多行next命令之前,首先需要看一下单行版本的next命令是如何工作的,然后就比较容易理解多行版本的next命令是如何操作的了。
1) 单行的next命令
       小写的n命令会告诉sed编辑器移动到数据流中的下一文本行,而不用重新回到命令的最开始再执行一遍。记住,通常sed编辑器在移动到数据流中的下一文本行之前,会在当前行上执行完所有定义好的命令。单行next命令改变了这个流程。
       这听起来可能有些复杂,没错,有时确实是。在这个例子中,你有个数据文件,共有5行内容,其中的两行是空的。目标是删除首行之后的空白行,而留下最后一行之前的空白行。如果写一个删掉空白行的sed脚本,你会删掉两个空白行。

$ cat data1.txt
This is the header line.
This is a data line.
This is the last line.
$
$ sed '/^$/d' data1.txt
This is the header line.
This is a data line.
This is the last line.
$

       由于要删除的行是空行,没有任何能够标示这种行的文本可供查找。解决办法是用n命令。在这个例子中,脚本要查找含有单词header的那一行。找到之后,n命令会让sed编辑器移动到文本的下一行,也就是那个空行。

$ sed '/header/{n ; d}' data1.txt
This is the header line.
This is a data line.
This is the last line.
$

       这时,sed编辑器会继续执行命令列表,该命令列表使用d命令来删除空白行。sed编辑器执行完命令脚本后,会从数据流中读取下一行文本,并从头开始执行命令脚本。因为sed编辑器再也找不到包含单词header的行了。所以也不会有其他行会被删掉。

2)合并文本行
       了解了单行版的next命令,现在来看看多行版的。单行next命令会将数据流中的下一文本行移动到sed编辑器的工作空间(称为模式空间)。多行版本的next命令(用大写N)会将下一文本行添加到模式空间中已有的文本后。
       这样的作用是将数据流中的两个文本行合并到同一个模式空间中。文本行仍然用换行符分隔,但sed编辑器现在会将两行文本当成一行来处理。
       下面的例子演示了N命令的工作方式。

$ cat data2.txt
This is the header line.
This is the first data line.
This is the second data line.
This is the last line.
$
$ sed '/first/{ N ; s/\n/ / }' data2.txt
This is the header line.
This is the first data line. This is the second data line.
This is the last line.
$

       sed编辑器脚本查找含有单词first的那行文本。找到该行后,它会用N命令将下一行合并到那行,然后用替换命令s将换行符替换成空格。结果是,文本文件中的两行在sed编辑器的输出中成了一行。
       如果要在数据文件中查找一个可能会分散在两行中的文本短语的话,这是个很实用的应用程序。这里有个例子。

$ cat data3.txt
On Tuesday, the Linux System
Administrator's group meeting will be held.
All System Administrators should attend.
Thank you for your attendance.
$
$ sed 'N ; s/System Administrator/Desktop User/' data3.txt
On Tuesday, the Linux System
Administrator's group meeting will be held.
All Desktop Users should attend.
Thank you for your attendance.
$

       替换命令会在文本文件中查找特定的双词短语System Administrator。如果短语在一行中的话,事情很好处理,替换命令可以直接替换文本。但如果短语分散在两行中的话,替换命令就没法识别匹配的模式了。
       这时N命令就可以派上用场了。

$ sed 'N ; s/System.Administrator/Desktop User/' data3.txt
On Tuesday, the Linux Desktop User's group meeting will be held.
All Desktop Users should attend.
Thank you for your attendance.
$

       用N命令将发现第一个单词的那行和下一行合并后,即使短语内出现了换行,你仍然可以找
到它。
       注意,替换命令在System和Administrator之间用了通配符模式(.)来匹配空格和换行符这两种情况。但当它匹配了换行符时,它就从字符串中删掉了换行符,导致两行合并成一行。这可能不是你想要的。
       要解决这个问题,可以在sed编辑器脚本中用两个替换命令:一个用来匹配短语出现在多行中的情况,一个用来匹配短语出现在单行中的情况。

$ sed 'N
> s/System\nAdministrator/Desktop\nUser/
> s/System Administrator/Desktop User/
> ' data3.txt
On Tuesday, the Linux Desktop
User's group meeting will be held.
All Desktop Users should attend.
Thank you for your attendance.
$

       第一个替换命令专门查找两个单词间的换行符,并将它放在了替换字符串中。这样你就能在
       第一个替换命令专门在两个检索词之间寻找换行符,并将其纳入替换字符串。这样就允许你在新文本的同样位置添加换行符了。
       但这个脚本中仍有个小问题。这个脚本总是在执行sed编辑器命令前将下一行文本读入到模式空间。当它到了最后一行文本时,就没有下一行可读了,所以N命令会叫sed编辑器停止。如果要匹配的文本正好在数据流的最后一行上,命令就不会发现要匹配的数据。

$ cat data4.txt
On Tuesday, the Linux System
Administrator's group meeting will be held.
All System Administrators should attend.
$
$ sed 'N
> s/System\nAdministrator/Desktop\nUser/
> s/System Administrator/Desktop User/
> ' data4.txt
On Tuesday, the Linux Desktop
User's group meeting will be held.
All System Administrators should attend.
$

       由于System Administrator文本出现在了数据流中的最后一行,N命令会错过它,因为没有其他行可读入到模式空间跟这行合并。你可以轻松地解决这个问题——将单行命令放到N命令前面,并将多行命令放到N命令后面,像这样:

$ sed '
> s/System Administrator/Desktop User/
> N
> s/System\nAdministrator/Desktop\nUser/
> ' data4.txt
On Tuesday, the Linux Desktop
User's group meeting will be held.
All Desktop Users should attend.
$

       现在,查找单行中短语的替换命令在数据流的最后一行也能正常工作,多行替换命令则会负责短语出现在数据流中间的情况。

2.多行删除命令
       sed编辑器用它来删除模式空间中的当前行。但和N命令一起使用时,使用单行删除命令就要小心了。

$ sed 'N ; /System\nAdministrator/d' data4.txt
All System Administrators should attend.
$

       删除命令会在不同的行中查找单词System和Administrator,然后在模式空间中将两行都删掉。这未必是你想要的结果。
       sed编辑器提供了多行删除命令D,它只删除模式空间中的第一行。该命令会删除到换行符(含换行符)为止的所有字符。

$ sed 'N ; /System\nAdministrator/D' data4.txt
Administrator's group meeting will be held.
All System Administrators should attend.
$

       文本的第二行被N命令加到了模式空间,但仍然完好。如果需要删掉目标数据字符串所在行的前一文本行,它能派得上用场。
       这里有个例子,它会删除数据流中出现在第一行前的空白行。

$ cat data5.txt
Th

你可能感兴趣的:(linux,shell)