Sed案例2
追加下一行
多行Next(N)命令通过读取新的输入行,并将它添加到模式空间的现有内容之后来创建多行模式空间。模式空间最初的内容和新的输入行之间用换行符分隔。在模式空间中嵌入的换行符可以利用转义序列“ ”来匹配。在多行模式空间中,元字符“^”匹配空间中的第一个字条,而不匹配换行符后面的字符。同样,“$”只匹配模式空间中最后的换行符,而不匹配任何嵌入的换行符,在执行next命令之后,控制将被传递给脚本中的后续命令。
Next命令与next命令不同,next输出模式空间的内容,然后读取新的输入行。next命令不创建多行模式空间。
例如,我们假设想要将“Owner and Operator Guide”换成“lnstallation Guide”,但是我们发现它出现在文件中的两行上,“Operator”和“Guide”被分开了。
//文本text内容如下
[root@yqh ~]# cat text
Consult Section 3.1 in the Owner and Operator
Guide for a description of the tape drives
available on your system.
//匹配以Operator结尾以及下行的Guide,合并成一行替换成Installation Guide
[root@yqh ~]# sed '/Operator$/{N;s/Operator
Guide/Installation Guide/g}' text
Consult Section 3.1 in the Owner and Installation Guide for a description of the tape drives
available on your system.
$!N
排除对最后一行($)执行Next命令。
//文本text1内容如下
[root@yqh ~]# cat text1
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.
//除最后一行,匹配Section,将所在行的Operator
Guide全局替换成Installation Guide
[root@yqh ~]# sed '/Section/{$!N;s/Operator
Guide/Installation Guide/g}' text1
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 Installation Guide for a description of the tape drives
available on your system.
转换Interleaf 文件
FrameMaker 和Interleaf 给出了WYSIWYG(所见即所得)技术发布包。它们两个都有能力读取和保存与普通二进制文件格式相对应的ASCII编码格式的文档内容。在这个例子中,我们将lnterleaf 文件转换成trooff ;然而,同一类型的脚本可以应用于将troff 编码的文件转换成Interleaf格式。这同样也适用于FrameMaker.它们两个都在文件中放置编码标签,由尖括号括起来。
实例1:
//文本text2内容如下
[root@yqh ~]# cat text2
<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>结尾的内容,将其写入fig.interleaf文件中,插入.FG
<insert figure here>
.FE内容,并删除匹配的内容
[root@yqh ~]# sed '
> /<Figure Begin>/,/<Figure End>/{
> w fig.interleaf
> /<Figure End>/i
> .FG
> <insert figure here>
> .FE
> d
> }' text2
<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.
[root@yqh ~]# cat fig.interleaf
<Figure Begin>
v.11111110000001111110000
1000001001000100000
000
<Figure End>
实例2:
//文本text1内容如下
[root@yqh ~]# cat text1
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结尾的内容,将其写入20210329文件中,插入Guide for a description of the tape drives
available on your system.内容,并删除匹配的内容
[root@yqh ~]# sed '
> /^Guide/,/^available/{
> w 20210329
> /available/i
> Guide for a description of the tape drives
available on your system.
> d
> }' text1
Consult Section 3.1 in the Owner and Operator
Guide for a description of the tape drives
available on your system.
[root@yqh ~]# cat 20210329
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)稍微有些不同:它删除模式空间中直到第一个嵌入的换行符的这部分内容。它不会导致读入新的输入行,相反,它返回到脚本的顶端,将这些指令应用于模式空间剩余的内容。
//文本text3内容如下
[root@yqh ~]# cat text3
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.
//匹配空行,并将它的下一行添加到模式空间合成一行,两行之间依然有换行符,匹配以
开头
结尾,如果匹配成功就删除,否则就不做操作
[root@yqh ~]# sed '/^$/{N;/^
$/d}' text3
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.
[root@yqh ~]# sed '/^$/{N;/^
$/D}' text3
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
当有偶数个空行时,所有的空行都会被删除。仅当有奇数个空行时,有一行被保留下来。这是因为删除命令清除的是整个模式空间。一旦遇到第一个空行,就读入下一行,并且两行都被删除。如果遇到第三个空行,并且下一行不为空,那么删除命令就不会被执行,因此空行被输出。如果使用多行Delete命令(是D不是d),就能得到我们想要的结果。
多行Delete命令完成工作的原因是,当遇到两个空行时,Delete命令只删除两个空行中的第一个。下一次遍历该脚本时,这个空行将导致另一行被读入模式空间。如果那行不为空,那么两行都输出,因此确保了输出一个空行。换句话说,当模式空间中有两个空行时、只有第一个空行被删除。当一个空行后面跟有文本时,模式空间可以正常输出。
多行打印
多行打印(Print)命令与小写字母的print命令稍有不同。该命令输出多行模式空间的第一部分,直到第一个嵌入的换行符为止。在执行完脚本的最后一个命令之后,模式空间的内容自动输出-n选项或#n抑制这个默认的动作)。因此,当默认的输出被抑制或者脚本中的控制流更改,以至不能到达脚本的底部时,需要使用打印命令(P或p) .Print命令经常出现在Next命令之后和Delete命令之前。这3个命令能建立一个输入/输出循环,用来维护两行的模式空间,但是一次只输出一行。这个循环的目的是只输出模式空间的第一行,然后返回到脚本的顶端将所有的命令应用于模式空间的第二行。没有这个循环,当执行脚本中的最后一个命令时,模式空间中的这两行都将被输出。
Next命令将一个新的输入行追加到模式空间的当前行。在替换命令应用于多行模式空间之后,模式空间的第一部分被Print命令输出,然后被Delete命令删除。这意味着当前被输出并且新的行成为当前行。Delete命令阻止脚本到达底部,这将输出两行并清除模式空间的内容。Delete命令让我们保护了模式空间的第二部分,并将控制转移动脚本的顶端,在顶端所有的编辑命令都可以被应用于一行。这些命令中有一个是Next命令,它将另一个新行读入模式空间。
实例1:
//text4内容如下
[root@yqh ~]# cat text4
Here are examples of the UNIX
System. Where UNIX
System appears, it should be the UNIX
Operating System.
[root@yqh ~]# sed '
/UNIX$/{
N
/
System/{
s// Operating &/
P
D
}}' text4
Here are examples of the UNIX Operating
System. Where UNIX Operating
System appears, it should be the UNIX
Operating System.
实例2:
//text5内容如下
[root@yqh ~]# cat text5
hello world runtime
yqh, where runtime
yqh, what runtime
it yqh.
[root@yqh ~]# sed '
> /runtime$/{
> N
> /
yqh/{
> s// it &/
> P
> D
> }}' text5
hello world runtime it
yqh, where runtime it
yqh, what runtime
it yqh.
包含那一行
模式空间是容纳当前输入行的缓冲区。还有-一个称为保持空间(hold space)的顶留(set-aside)缓冲区。模式空间的内容可以复制到保持空间,而且保持空间的内容也可以复制到模式空间。有一组命令用于在保持空间和模式空间之间移动数据。保持空间用于临时存储。单独的命令不能寻址保持空间或者更改它的内容。
保持空间最常的用途是,当改变模式空间中的原始内容时,用于保留当前输入行的副本。影响模式空间的命令有:
命令 | 缩写 | 功能 |
---|---|---|
Hold | h 或 H | 将模式空间的内容复制或追加到保持空间 |
Get | g 或 G | 将保持空间的内容复制或追加到模式空间 |
Exchange | x | 交换保持空间和模式空间的内容 |
这些命令中的每一条都可以利用一个地址来指定一行或行范围。Hole(h,H)命令将数据移至保持空间、而get (g.G)命令将保持空间的数据移回到模式空间。同一命令的小写字母和大写字母之间的差别是,小字字母命令改写目的缓存区的内容,而大写字母命令追加缓存区的现有内容。
Hole命令在保持空间的内容之后放置一个换行符,且后面跟随模式空间的内容(即使保持空间是空的,换行符也被追加到保持空间中)。Get命令模式空间的内容之后放置一个换行符,且后面跟随保持空间的内容。
交换命令交换两个缓存区的内容,对两个缓存区没有副作用。
//文本text6内容如下
[root@yqh ~]# cat text6
1
2
11
22
111
222
//这里的目的是颠倒以1开始的行和以2开始的行的顺序,将第一行复制到保持空间(它一直在那),这时清除模式空间,然后sed将第二行读入模式空间,并且将保持空间的行追加到模式空间的结尾
[root@yqh ~]# sed '
> /1/{
> h
> d
> }
> /2/{
> G
> }' text6
2
1
22
11
222
111
[root@yqh ~]# sed '
/1/{
h
d
}
/2/{
g
}' text6
1
11
111
匹配“1”的任何行都被复制到保持空间并且从模式空间删除,控制转移到脚本的顶端并且不打印那一行,当读取下一行时,它匹配模式“2”且将已经复制到保持空间的行追加到模式空间之后,然后两行都被打印出来,保存这两行中的第一行并且直到匹配第二行时才输出它。
构建文本块
保持空间可用于在输出行块之前收集它们,一些troff请求和宏是面向块的,这命令中必须包围文件块。通常在块开始处的代码用启用格式,而大块结尾处的代码用禁用格式。HTML编码的文档还包含许多面向块的结构。例如,“《p》”和“《/p》”分别用于开始和结束一个段落。输入文件包含由可变长度的行组成的段落,段落之间都有一个空行。因此,脚本必须将空行之前的所有行收集到保持空间。检索保持空间的内容并且用段落标签包围这些内容。
//文本text7内容如下
[root@yqh ~]# cat text7
hello world
hello runtime
abc
def
123
456
end
[root@yqh ~]# sed '
> /^$/!{
> H
> d
> }
> /^$/{
> x
> s/^
/<p>/
> s/$/</p>/
> G
> }' text7
<p>hello world
hello runtime</p>
<p>abc
def</p>
<p>123
456</p>