高级sed命令
高级命令分成了3个组:
- 处理了多行模式空间(N、D、P)
- 采用保持空间来保存模式空间的内容并使它可用于后续的命令(H、h、G、g、x)
- 编写使用分支和条件指令的脚本来更改控制流(:、b、 t)
多行模式空间
在前面正则表达式的讨论中,我们强调模式匹配是面向行的。像grep这样的程序尝试在单个输入行上匹 配一个模式。这就使它很难匹配一个在一行的结尾处开始。并在下一行的开始处结束的短语。其他一些 模式只有当在多行上重复时才有意义。
sed能查看模式空间的多个行,这就是允许匹配模式扩展到多行上,3个多行命令(N、D、P))对应于小 写字母的基本命令(n、d、p)。例如,删除命令(D)是删除命令(d)的多行形式。区别是:d删除模 式空间的内容,D只删除多行模式空间的第一行。
多行命令
多行Next(N)命令通过读取新的输入行,并将它添加到模式空间的现有内容之后来创建多行模式空间。模式空间最初的内容和新的输入行之间用换行符分隔。在模式空间中嵌入的换行符可以利用转义序列“\n”来匹配。在多行模式空间中,元字符“^”匹配空间中的第一个字条,而不匹配换行符后面的字符。同样,“$”只匹配模式空间中最后的换行符,而不匹配任何嵌入的换行符。在执行next命令之后,控制将被传递给脚本中的后续命令。
Next命令与next命令不同,next输出模式空间的内容,然后读取新的输入行。next命令不创建多行模式空间。
N
#示例文件
[root@localhost ~]# cat list
John Daggett, 341 King Road, Plymouth MA
Alice Ford, 22 East Broadway, Richmond VA
Orville Thomas, 11345 Oak Bridge Road, Tulsa OK
Terry Kalkas, 402 Lans Road, Beaver Falls PA
Eric Adams, 20 Post ROad, Sudbury MA
Hubert Sims, 328A Brook Road, Roanoke VA
Amy Wilde, 334 Bayshore Pkwy, Mountain View CA
Sal Carpenter, 73 6th Street, Boston MA
#把两行替换成一行
[root@localhost ~]# sed -r '/Thomas/{N;s/OK\nTerry/123456/g}' list
John Daggett, 341 King Road, Plymouth MA
Alice Ford, 22 East Broadway, Richmond VA
Orville Thomas, 11345 Oak Bridge Road, Tulsa 123456 Kalkas, 402 Lans Road, Beaver Falls PA
Eric Adams, 20 Post ROad, Sudbury MA
Hubert Sims, 328A Brook Road, Roanoke VA
Amy Wilde, 334 Bayshore Pkwy, Mountain View CA
Sal Carpenter, 73 6th Street, Boston MA
$!N
它排除了对最后一行($)执行Next命令,除非使用“$!N”语法
#示例文件
[root@localhost ~]# cat file
Consult Section 3.1 in the Owner and operator
Guide for a description of the tape drives
Consult Section 3.1 in the Owner and operator
Guide for a description of the tape drives
Consult Section 3.1 in the Owner and Operator
Guide for a description of the tape drives
available on your system.
#除了最后一行全部打印出来
[root@localhost ~]# sed -n '/Section/{$!N;p}' file
Consult Section 3.1 in the Owner and operator
Guide for a description of the tape drives
Consult Section 3.1 in the Owner and operator
Guide for a description of the tape drives
Consult Section 3.1 in the Owner and Operator
Guide for a description of the tape drives
#匹配Section,把opetator换行Guide,合并为一行,全局替换为Installation,最后一行不操作
[root@localhost ~]# sed '/Section/{$!N;s/operator\nGuide/Installation Guide/g}' file
Consult Section 3.1 in the Owner and Installation Guide for a description of the tape drives
Consult Section 3.1 in the Owner and Installation Guide for a description of the tape drives
Consult Section 3.1 in the Owner and Operator
Guide for a description of the tape drives
available on your system.
转换Interleaf文件
FrameMaker 和lnterleaf 给出了WYSIWYG(所见即所得)技术发布包。它们两个都有能力读取和保存与普通二进制文件格式相对应的ASCII编码格式的文档内容。在这个例子中,我们将Interleaf文件转换成trooff;然而,同一类型的脚本可以应用于将troff 编码的文件转换成Interleaf格式。这同样也适用于FrameMaker.它们两个都在文件中放置编码标签,由尖括号括起来。
步骤:
先匹配内容--->把内容插入一个文件--->删除匹配内容--->生成一个文件
示例:
//实例一
#示例文件
[root@localhost ~]# cat 123
<para>
This is a test paragraph in Interleaf style ASCII. Another line
in a paragraph. Yet another.
<Figure Begin>
v.11111110000001111110000
1000001001000100000
000
<Figure End>
<para>
More lines of text to be found after the figure.
These lines should print.
#"删除"<Figure Begin>和<Figure End>中间的内容
[root@localhost ~]# sed '
> /<Figure Begin>/,/<Figure End>/{
> w fig.interleaf
> /<Figure End>/i\
> .FG\
> <insert figure here>\
> .FE
> d
> }' 123
<para>
This is a test paragraph in Interleaf style ASCII. Another line
in a paragraph. Yet another.
.FG
<insert figure here>
.FE
<para>
More lines of text to be found after the figure.
These lines should print.
#查看删除的内容,本地会有一个fig.interleaf文件
[root@localhost ~]# ls
123 byState file list newlist sedscr
abc fig.interleaf file1 nameState phonenum test
[root@localhost ~]# cat fig.interleaf
<Figure Begin>
v.11111110000001111110000
1000001001000100000
000
<Figure End>
//实例二
#示例文件
[root@localhost ~]# cat file
Consult Section 3.1 in the Owner and operator
Guide for a description of the tape drives
Consult Section 3.1 in the Owner and operator
Guide for a description of the tape drives
Consult Section 3.1 in the Owner and Operator
Guide for a description of the tape drives
available on your system.
#匹配以Guide开头,available结尾的部分,把匹配到的内容写入456文件,然后插入Guide for a description of the tape drives\navailable on your system.内容,删除匹配到的内容
[root@localhost ~]# sed '
/^Guide/,/^available/{
w 456
/available/i\
Guide for a description of the tape drives\navailable on your system.
d
}' file
Consult Section 3.1 in the Owner and operator
Guide for a description of the tape drives
available on your system.
//查看刚才"删除"的内容
[root@localhost ~]# cat 456
Guide for a description of the tape drives
Consult Section 3.1 in the Owner and operator
Guide for a description of the tape drives
Consult Section 3.1 in the Owner and Operator
Guide for a description of the tape drives
available on your system.
多行删除
删除命令(d)删除模式空间的内容并导致读入新的输入行,从而在脚本的顶端重新使用编辑方法。删除命令(D)稍微有些不同:它删除模式空间中直到第一个嵌入的换行符的这部分内容。它不会导致读入新的输入行,相反,它返回到脚本的顶端,将这些指令应用于模式空间剩余的内容。
示例:
#示例文件
[root@localhost ~]# cat file2
This line is followed by 1 blank line
This line is followed by 2 blank line
This line is followed by 3 blank line
This line is followed by 4 blank line
This is the end.
//匹配空行,并将它的下一行添加到模式空间合成一行,两行之间依然有换行符,匹配以\n开头\n结尾,如果匹配成功就删除,否则就不做操作
#d
[root@localhost ~]# sed '/^$/{N;/^\n$/d}' file2
This line is followed by 1 blank line
This line is followed by 2 blank line
This line is followed by 3 blank line
This line is followed by 4 blank line
This is the end.
#D
[root@localhost ~]# sed '/^$/{N;/^\n$/D}' file2
This line is followed by 1 blank line
This line is followed by 2 blank line
This line is followed by 3 blank line
This line is followed by 4 blank line
This is the end.
多行打印
多行打印(Print)命令与小写字母的print命令稍有不同。该命令输出多行模式空间的第一部分,直到第一个嵌入的换行符为止。在执行完脚本的最后一个命令之后,模式空间的内容自动输出-n选项或#n抑制这个默认的动作)。因此,当默认的输出被抑制或者脚本中的控制流更改,以至不能到达脚本的底部时,需要使用打印命令(P或p) .Print命令经常出现在Next命令之后和Delete命令之前。这3个命令能建立一个输入/输出循环,用来维护两行的模式空间,但是一次只输出一行。这个循环的目的是只输出模式空间的第一行,然后返回到脚本的顶端将所有的命令应用于模式空间的第二行。没有这个循环,当执行脚本中的最后一个命令时,模式空间中的这两行都将被输出。
Next命令将一个新的输入行追加到模式空间的当前行。在替换命令应用于多行模式空间之后,模式空间的第一部分被Print命令输出,然后被Delete命令删除。这意味着当前被输出并且新的行成为当前行。Delete命令阻止脚本到达底部,这将输出两行并清除模式空间的内容。Delete命令让我们保护了模式空间的第二部分,并将控制转移动脚本的顶端,在顶端所有的编辑命令都可以被应用于一行。这些命令中有一个是Next命令,它将另一个新行读入模式空间。
#示例文件
[root@localhost ~]# cat file3
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 &/;P;D}}' file3
Here are examples of the UNIX Operating
System. Where UNIX Operating
System appears, it should be the UNIX
Operating System.
保持空间
模式空间是容纳当前输入行的缓冲区。还有-一个称为保持空间(hold space)的顶留(set-aside)缓冲区。模式空间的内容可以复制到保持空间,而且保持空间的内容也可以复制到模式空间。有一组命令用于在保持空间和模式空间之间移动数据。保持空间用于临时存储。单独的命令不能寻址保持空间或者更改它的内容。
保持空间最常的用途是,当改变模式空间中的原始内容时,用于保留当前输入行的副本。影响模式空间的命令有:
命令 | 缩写 | 功能 |
Hold | h 或 H | 将模式空间的内容复制或追加到保持空间 |
Get | g 或 G | 将保持空间的内容复制或追加到模式空间 |
Exchange | x | 交换保持空间和模式空间的内容 |
这些命令中的每一条都可以利用一个地址来指定一行或行范围。Hole(h,H)命令将数据移至保持空间、而get (g.G)命令将保持空间的数据移回到模式空间。同一命令的小写字母和大写字母之间的差别是,小字字母命令改写目的缓存区的内容,而大写字母命令追加缓存区的现有内容。
Hole命令在保持空间的内容之后放置一个换行符,且后面跟随模式空间的内容(即使保持空间是空的,换行符也被追加到保持空间中)。Get命令模式空间的内容之后放置一个换行符,且后面跟随保持空间的内容。
交换命令交换两个缓存区的内容,对两个缓存区没有副作用。
构建文本块
保持空间可用于在输出行块之前收集它们,一些troff请求和宏是面向块的,这命令中必须包围文件块。通常在块开始处的代码用启用格式,而大块结尾处的代码用禁用格式。HTML编码的文档还包含许多面向块的结构。
例如,< p >和< /p >分别用于开始和结束一个段落。输入文件包含由可变长度的行组成的段落,段落之间都有一个空行。因此,脚本必须将空行之前的所有行收集到保持空间。
检索保持空间的内容并且用段落标签包围这些内容。
示例:
#示例文件
[root@localhost ~]# cat abcd
hello world
hello leidazhuang
name
ldaz
age
18
end
[root@localhost ~]# sed '
/^$/!{
H
d
}
/^$/{
x
s/^\n/<p>/
s/$/<\/p>/
G
}' abcd
<p>hello world
hello leidazhuang</p>
<p>name
ldaz</p>
<p>age
18</p>