多行模式空间
在前面正则表达式的讨论中,我们强调模式匹配是面向行的。像grep这样的程序尝试在单个输入行上匹配一个模式。这就使它很难匹配一个在一行的结尾处开始。并在下一行的开始处结束的短语。其他一些模式只有当在多行上重复时才有意义。(比如有的句子太长了,在跨行中使用)
sed能查看模式空间的多个行。这就是允许匹配模式扩展到多行上。在本节中,我们将来看一下创建多行模式空间并处理它的内容的命令。这里的3个多行命令(N、D、P)对应于上一章出现的小写字母的基本命令(n、d、p)。例如,删除命令(D)是删除命令(d)的多行形式。区别是:d删除模式空间的内容,D只删除多行模式空间的第一行。
追加下一行
多行Next(N))命令通过读取新的输入行,并将它添加到模式空间的现有内容之后来创建多行模式空间。模式空间最初的内容和新的输入行之间用换行符分隔。在模式空间中嵌入的换行符可以利用转义序列“\n”来匹配。在多行模式空间中,元字符“^”匹配空间中的第一个字条,而不匹配换行符后面的字符。同样,“$”只匹配模式空间中最后的换行符,而不匹配任何嵌入的换行符。在执行next命令之后,控制将被传递给脚本中的后续命令。
Next命令与next命令不同,next输出模式空间的内容,然后读取新的输入行。next命令不创建多行模式空间。
#实例1
//文档
[root@localhost ~]# cat abc
Consult Section 3.1 in the Owner and Operator
Guide for a description of the tape drives
available on your system.
//改变
[root@localhost ~]# sed '/Operator$/{N;s/Owner and Operator\nGuide/installation Guide/g}' abc
Consult Section 3.1 in the installation Guide for a description of the tape drives
available on your system.
//拆解
[root@localhost ~]# sed -n '/Operator$/{N;p}' abc //匹配以Operator结尾的行 N和匹配行的下一行 p打印
Consult Section 3.1 in the Owner and Operator
Guide for a description of the tape drives
[root@localhost ~]# sed -n '/Operator$/{N;s/Owner and Operator\nGuide/installation Guide/g ;p}' abc //将Owner and Operator\nGuide 变成 installation Guide 因为替换包括了\n(转行) 所以打印时会将两条显示为一条
Consult Section 3.1 in the installation Guide for a description of the tape drives
#实例2
//文档
[root@localhost ~]# cat abc
Consult Section 3.1 in the Owner and Operator
Guide for a description of the tape drives
available on your system.
Look in the Owner and Operator Guide shipped with your system.
Two manuals are provided inc luding the Owner and
Operator Guide and the User Gui de.
The Owner and Operator Guide is shipped with your system.
//改变
[root@localhost ~]# sed 's/Owner and Operator Guide/installation Guide/g;/Owner/{N;s/ *\n/ /g;s/Owner and Operator Guide */installation Guide\n/g}' abc
Consult Section 3.1 in the installation Guide
for a description of the tape drives
available on your system.
Look in the installation Guide shipped with your system.
Two manuals are provided inc luding the installation Guide
and the User Gui de.
The installation Guide is shipped with your system.
//拆解
[root@localhost ~]# sed 's/Owner and Operator Guide/installation Guide/g' abc //将Owner and Operator Guide替换为installation Guide
Consult Section 3.1 in the Owner and Operator
Guide for a description of the tape drives
available on your system.
Look in the installation Guide shipped with your system.
Two manuals are provided inc luding the Owner and
Operator Guide and the User Gui de.
The installation Guide is shipped with your system.
[root@localhost ~]# sed -n 's/Owner and Operator Guide/installation Guide/g;/Owner/p' abc //匹配带有Owner的行(此时只有两行)
Consult Section 3.1 in the Owner and Operator
Two manuals are provided inc luding the Owner and
[root@localhost ~]# sed -n 's/Owner and Operator Guide/installation Guide/g;/Owner/{N;p}' abc //将匹配行的下一行追加到模式空间
Consult Section 3.1 in the Owner and Operator
Guide for a description of the tape drives
Two manuals are provided inc luding the Owner and
Operator Guide and the User Gui de.
[root@localhost ~]# sed -n 's/Owner and Operator Guide/installation Guide/g;/Owner/{N;s/ *\n/ /g;p}' abc //将 *\n替换为空格 就变成了两行合并为一行
Consult Section 3.1 in the Owner and Operator Guide for a description of the tape drives
Two manuals are provided inc luding the Owner and Operator Guide and the User Gui de.
[root@localhost ~]# sed -n 's/Owner and Operator Guide/installation Guide/g;/Owner/{N;s/ *\n/ /g;s/Owner and Operator Guide */installation Guide\n/g;p}' abc //将Owner and Operator Guide * 替换为installation Guide\n 改变了Owner and Operator Guide然后后面的换行
Consult Section 3.1 in the installation Guide
for a description of the tape drives
Two manuals are provided inc luding the installation Guide
and the User Gui de.
多行删除
删除命令(d)删除模式空间的所有内容并导致读入新的输入行,从而在脚本的顶端重新使用编辑方法。删除命令(D)稍微有些不同:它删除模式空间中第一行的内容,它不会导致读入新的输入行,相反,它返回到脚本的顶端,将这些指令应用于模式空间剩余的内容,我们可以编写一个实现查找一系列空行并输出单个空行的脚本,以看看它们之间的区别。下面的语句使用了删除命令(d):
#将多个空行减少到一行,利用d命令的版本
/- $/{
N
/-\n$/d
}
当遇到一个空行时,下一行就追加到模式空间中。然后试着匹配嵌入的换行符。注意定位元字符^和$分别匹配模式空间的开始处和结束处。
#实例1
//文档
[root@localhost ~]# cat abc
This 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 b lank lines.
This is the end.
//改变
[root@localhost ~]# sed '/^$/{N;/^\n$/d}' abc
This 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 b lank lines.
This is the end.
//拆解
[root@localhost ~]# sed -n '/^$/{N;p}' abc //匹配空行将匹配行的下一行追加到模式空间
This line is followed by 2 blank lines.
This line is followed by 4 b lank lines.
[root@localhost ~]# sed -n '/^$/{N;/^\n$/d;p}' abc //以换行符开头或结尾的删除(空格偶数删除)
This line is followed by 2 blank lines.
This line is followed by 4 b lank lines.
多行打印
多行打印(Print)命令与小写字母的print命令稍有不同。该命令输出多行模式空间的第一部分,直到第一个嵌入的换行符为止。在执行完脚本的最后一个命令之后,模式空间的内容自动输出(-n选项或#n抑制这个默认的动作)。因此,当默认的输出被抑制或者脚本中的控制流更改,以至不能到达脚本的底部时,需要使用打印命令(P或p) .Print命令经常出现在Next命令之后和Delete命令之前。这3个命令能建立一个输入/输出循环,用来维护两行的模式空间,但是一次只输出一行。这个循环的目的是只输出模式空间的第一行,然后返回到脚本的顶端将所有的命令应用于模式空间的第二行。没有这个循环,当执行脚本中的最后一个命令时,模式空间中的这两行都将被输出。创建多行模式空间以匹配第一行结尾处的“UNIX”和第二行开始处的“System”。如果发现“UNIX System”跨越两行,那么我们将它变成“UNIX OperatingSystem”。建立这个循环以返回到脚本的顶端,并寻找第二行结尾处的
Next命令将一个新的输入行追加到模式空间的当前行。在替换命令应用于多行模式空间之后,模式空间的第一部分被Print命令输出,然后被Delete命令删除。这意味着当前被输出并且新的行成为当前行。Delete命令阻止脚本到达底部,这将输出两行并清除模式空间的内容。Delete命令让我们保护了模式空间的第二部分,并将控制转移动脚本的顶端,在顶端所有的编辑命令都可以被应用于一行。这些命令中有一个是Next命令,它将另一个新行读入模式空间。
下面的脚本实现了同样的循环:
/UNIX$/{
N
/\nSystem/ {
s// 0perating &/
p
D
}
}
替换命令匹配“\nSystem”,并且用“Operating\nSystem”取代它。保留换行是很重要的,否则模式空间中就有只一行。注意Print和Delete命令的顺序。
#实例1
//文件
[root@localhost ~]# cat abc
Here are examples of the UNIX
System. Where UNIX
System appears,it should be the UNIX
Operating System.
//改变
[root@localhost ~]# sed '/UNIX$/{N;/\nSystem/{s// Operating &/g;P;D}}' abc
Here are examples of the UNIX Operating
System. Where UNIX Operating
System appears,it should be the UNIX
Operating System.
//拆解
[root@localhost ~]# sed -n '/UNIX$/{N;p}' abc //匹配UNIX结尾的行 将匹配到行的下一行添加到模式空间
Here are examples of the UNIX
System. Where UNIX
System appears,it should be the UNIX
Operating System.
[root@localhost ~]# sed -n '/UNIX$/{N;/\nSystem/{p}}' abc // /\nSystem/ 在匹配转行后为System的行
Here are examples of the UNIX
System. Where UNIX
[root@localhost ~]# sed -n '/UNIX$/{N;/\nSystem/{s// Operating &/g;p}}' abc //添加Operating
Here are examples of the UNIX Operating
System. Where UNIX
[root@localhost ~]# sed -n '/UNIX$/{N;/\nSystem/{s// Operating &/g;P}}' abc //P打印模式空间第一行
Here are examples of the UNIX Operating
[root@localhost ~]# sed -n '/UNIX$/{N;/\nSystem/{s// Operating &/g;P;D}}' abc //删除模式空间的第一行
Here are examples of the UNIX Operating
System. Where UNIX Operating
包含那一行
模式空间是容纳当前输入行的缓冲区。还有一个称为保持空间(hold space)的顶留(set-aside)缓冲区。模式空间的内容可以复制到保持空间,而且保持空间的内容也可以复制到模式空间。有一组命令用于在保持空间和模式空间之间移动数据。保持空间用于临时存储。单独的命令不能寻址保持空间或者更改它的内容。
保持空间最常的用途是,当改变模式空间中的原始内容时,用于保留当前输入行的副本。影响模式空间的命令有:
这些命令中的每一条都可以利用一个地址来指定一行或行范围。Hole(h,H)命令将数据移至保持空间、而get (g.G)命令将保持空间的数据移回到模式空间。同一命令的小写字母和大写字母之间的差别是,小字字母命令改写目的缓存区的内容,而大写字母命令追加缓存区的现有内容。
Hold 命令用模式空间的内容取代保持空间的内容。get命令用保持空间的内容取代模式空间的内容。
Hole命令在保持空间的内容之后放置一个换行符,且后面跟随模式空间的内容(即使保持空间是空的,换行符也被追加到保持空间中)。Get命令模式空问的内容之后放置一个换行符,且后面跟随保持空间的内容。
交换命令交换两个缓存区的内容,对两个缓存区没有副作用。
#实例1
//文件
[root@localhost ~]# cat abc
1
2
11
22
111
222
//变化
[root@localhost ~]# sed -n '/1/{h;d};/2/{G};p' abc
2
1
22
11
222
111
[root@localhost ~]# sed -n '/1/{h;d};p' abc //将模式空间的1追加到保持空间 并删除模式空间的1
2
22
222