1. sed高级命令介绍
高级脚本都做一件共同的事,那就是它们改变了执行或控制的流程顺序。通常,一行被读入模式空间并且用脚本中的每个命令(一个接一个地)应用于那一行。当达到脚本的底部时,输出这一行并且清空模式空间。然后新行被读入模式空间,并且控制被转移回脚本的顶端。这是sed 脚本中正常的控制流。
脚本由于各种原因中断或暂停了正常的控制流。它们也许想阻止脚本中的命令被执行,某些特定的情况除外,或者阻止模式空间的内容被清除。更改控制流会使脚本更加难以阅读和理解。事实上,写脚本比读脚本更容易。当你编写很难的脚本时,测式它来看看命令如何工作对你会有好处。
sed在正常情况下,将处理的行读入模式空间(pattern space)脚本中的“sed-command(sed命令)”就一条接着一条进行处理,直到脚本执行完毕。然后该行被输出,模式(pattern space)被清空;接着,在重复执行刚才的动作,文件中的新的一行被读入,直到文件处理完毕。(就是追加下一行)
//写一个测试文件,以下实验皆基于此测试文件的内容
[root@localhost ~]# cat > abc <<EOF
> The world is spl
> endid and grand.Welco
> me home
> EOF
[root@localhost ~]# cat abc
The world is spl
endid and grand.Welco
me home
2. N命令使用
N追加,将下一行添加到pattern space中。将当前读入行和用N命令添加的下一行看成“一行”
//把换行符替换成空,\n表示换行符
[root@localhost ~]# sed '/spl/N;s/\n//' abc
The world is splendid and grand.Welco
me home
//把e替换成b
[root@localhost ~]# sed '/spl/N;s/\ne/b/' abc
The world is splbndid and grand.Welco
me home
//写一个文件,进行处理
[root@localhost ~]# cat test
/spl/{
N;s/\n//}
[root@localhost ~]# sed -f test abc
The world is splendid and grand.Welco
me home
//写一个文件处理多行,对空格进行处理
[root@localhost ~]# cat test
/spl/{
N;s/\n//
N;s/\n //
}
[root@localhost ~]# sed -f test abc
The world is splendid and grand.Welcome home
//在命令行输入
[root@localhost ~]# sed '/spl/{N;s/\n//;N;s/\n //}' abc
The world is splendid and grand.Welcome home
3. D命令使用
sed命令之D命令:
如果模式空间包含换行符,则删除直到第一个换行符的模式空间中的文本, 并不会读取新的输入行,而使用合成的模式空间重新启动循环。如果模式空间 不包含换行符,则会像发出d命令那样启动正常的新循环。(删除第一行,但第二行保留)
//匹配spl然后删除
[root@localhost ~]# sed '/spl/d' abc
endid and grand.Welco
me home
//多行模式空间进行删除
[root@localhost ~]# sed '/spl/{N;D}' abc
endid and grand.Welco
me home
//执行两个任务,删除两行
[root@localhost ~]# sed '/spl/{N;D};/Welco/{N;D}' abc
me home
4.P多行打印命令
同d 和 D 之间的区别一样,P(大写)命令和单行打印命令 p(小写)不同,对于具有多行数据的缓冲区来说,它只会打印缓冲区中的第一行,也就是首个换行符之前的所有内容。
//text文件中内容
[root@localhost ~]# cat text
Here are example of the UNIX
System. Where UNIX
System appears, it should be the UNIX
Operating System
使用P命令
[root@localhost ~]# cat aaa
/UNIX$/{
N
/\nSystem/{
s// Operating &/
P
D
}
}
[root@localhost ~]# sed -f aaa text
Here are example of the UNIX Operating
System. Where UNIX Operating
System appears, it should be the UNIX
Operating System
5. sed保持空间
sed 命令处理的是缓冲区中的内容,其实这里的缓冲区,应称为模式空间。模式空间并不是 sed 命令保存文件的唯一空间。sed 还有另一块称为保持空间的缓冲区域,它可以用来临时存储一些数据。
命令 | 功能 |
---|---|
h | 将模式空间中的内容复制到保持空间 |
H | 将模式空间中的内容附加到保持空间 |
g | 将保持空间中的内容复制到模式空间 |
G | 将保持空间中的内容附加到模式空间 |
x | 交换模式空间和保持空间中的内容 |
通常,在使用 h 或 H 命令将字符串移动到保持空间后,最终还要用 g、G 或 x 命令将保存的字符串移回模式空间。保持空间最直接的作用是,一旦我们将模式空间中所有的文件复制到保持空间中,就可以清空模式空间来加载其他要处理的文本内容。
[root@localhost ~]# cat my.txt
This is the header line.
This is the first data line.
This is the second data line.
This is the last line.
[root@localhost ~]# sed -n '/first/ {h ; p ; n ; p ; g ; p }' my.txt
This is the first data line.
This is the second data line.
This is the first data line.
运行过程:
sed脚本命令用正则表达式过滤出含有单词first的行;
当含有单词 first 的行出现时,h 命令将该行放到保持空间;
p 命令打印模式空间也就是第一个数据行的内容;
n 命令提取数据流中的下一行(This is the second data line),并将它放到模式空间;
p 命令打印模式空间的内容,现在是第二个数据行;
g 命令将保持空间的内容(This is the first data line)放回模式空间,替换当前文本;
p 命令打印模式空间的当前内容,现在变回第一个数据行了。
[root@my ~]# cat list
find the match statement uagidvbiyhavwi
abcde the tom statement uagidvbiyhavwi
abcde the jerry statement uagidvbiyhavwi
[root@my ~]# cat sedscript
/the .* statement/{
h
s/.*the (.*) statement.*/\1/ }
[root@my ~]# sed -rf sedscript list
Match
tom
jerry
#基于以上,再将3行内容换成大写
[root@my ~]# cat sedscript
/the .* statement/{
h
s/.*the (.*) statement.*/\1/
y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
}
[root@my ~]# sed -rf sedscript list
MATCH
TOM
JERRY
#再基于以上,将保持空间的内容全部复制到模式空间,调换位置即可
root@my ~]# cat sedscript
/the .* statement/{
h
s/.*the (.*) statement.*/\1/
y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
G
s/(.*)\n(.*the) .*(statement)/\2 \1 \3/
}
[root@my ~]# sed -rf sedscript list
find the MATCH statement uagidvbiyhavwi
abcde the TOM statement uagidvbiyhavwi
abcde the JERRY statement uagidvbiyhavwi
#以上均是呈现的模式空间的效果
[root@my ~]# sed -i -r -f sedscript list
[root@my ~]# cat list
find the MATCH statement uagidvbiyhavwi
abcde the TOM statement uagidvbiyhavwi
abcde the JERRY statement uagidvbiyhavwi
6.b分支命令
b 分支命令
通常,sed 程序的执行过程会从第一个脚本命令开始,一直执行到最后一个脚本命令(D 命令是个例外,它会强制 sed 返回到脚本的顶部,而不读取新的行)。sed 提供了 b 分支命令来改变命令脚本的执行流程,其结果与结构化编程类似。
b 分支命令基本格式为:
[address]b [label]
其中,address 参数决定了哪些行的数据会触发分支命令,label 参数定义了要跳转到的位置。
需要注意的是,如果没有加 label 参数,跳转命令会跳转到脚本的结尾,比如:
[root@localhost ~]# 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.
[root@localhost ~]# sed '{2,3b ; s/This is/Is this/ ; s/line./test?/}' data2.txt
Is this the header test?
This is the first data line.
This is the second data line.
Is this the last test?
可以看到,因为 b 命令未指定 label 参数,因此数据流中的第2行和第3行并没有执行那两个替换命令。
如果我们不想直接跳到脚本的结尾,可以为 b 命令指定一个标签(也就是格式中的 label,最多为 7 个字符长度)。在使用此该标签时,要以冒号开始(比如 :label2),并将其放到要跳过的脚本命令之后。这样,当 sed 命令匹配并处理该行文本时,会跳过标签之前所有的脚本命令,但会执行标签之后的脚本命令
比如:
[root@localhost ~]# sed '{/first/b jump1 ; s/This is the/No jump on/
> :jump1
> s/This is the/Jump here on/}' data2.txt
No jump on header line
Jump here on first data line
No jump on second data line
No jump on last line
在这个例子中,如果文本行中出现了 first,程序的执行会直接跳到 jump1 标签之后的脚本行。如果分支命令的模式没有匹配,sed 会继续执行所有的脚本命令。