1、模式空间与保持空间
模拟空间:
当前处理输出的缓冲空间,因为sed就是一次处理一行的内容,就会把这一行的内容提取到模式空间,然后用sed命令处理这一行的内容,处理完成后输出到屏幕,接着处理下一行 的内容
保持空间:
保持空间就是sed的另一个缓冲区,此缓冲区如其名,不会自动清空内容,也不会把缓冲区的内容打印到的标准输出中。
1.1命令选项
- P:打印模式空间开端至\n内容,并追加到默认输出之前
- h: 把模式空间中的内容覆盖至保持空间中
- H:把模式空间中的内容追加至保持空间中
- g: 从保持空间取出数据覆盖至模式空间
- G:从保持空间取出内容追加至模式空间
- x: 把模式空间中的内容与保持空间中的内容进行互换
- n: 读取匹配到的行的下一行覆盖至模式空间,打印模式空间的值,并读取下一行。
- N:读取匹配到的行的下一行追加至模式空间,它不打印模式空间的值
- d: 删除模式空间中的行
- D:如果模式空间包含换行符,则删除直到第一个换行符的模
2、模式空间
sed多行命令
在学习 sed 命令的基础功能时,大家可能注意到了一个局限,即所有的 sed 命令都只是针对单行数据执行操作,在 sed 命令读取缓冲区中的文本数据时,它会基于换行符的位置,将数据分成行,sed 会根据定义好的脚本命令一次处理一行数据,如果一个内容在两行中那么就不好处理了。而sed多行命令则可以解决这些问题。
- Next 命令(N):将数据流中的下一行加进来创建一个多行组来处理。
- Delete(D):删除多行组中的一行。
- Print(P):打印多行组中的一行。
2.1 多行命令演示(N/n)
// 这个例子中,sed先查找含有filest单词的哪行文本,然后在用N命令将下一行内容也添加到模式空间中,此时模式空间就有两行内容了,然后再用s命令将换行符\n换成空格
[root@ansible ~]# cat test01.txt
This is the header line.
This is the first data line.
This is the second data line.
This is the last line.
[root@ansible ~]# sed '/first/{ N ; s/n/ / }' test01.txt
This is the header line.
This is the first data line. This is the second data line.
This is the last line.
2.2 多行删除命令(D/d)
sed 不仅提供了单行删除命令(d),也提供了多行删除命令 D,其作用是只删除缓冲区中的第一行,也就是说,D 命令将缓冲区中第一个换行符(包括换行符)之前的内容删除掉。
演示:
删除数据流中出现在第一行前的空白行,sed会查找空白行,然后用 N 命令来将下一文本行添加到模拟空间。此时如果模拟空间的内容中含有单词 header,则 D 命令会删除缓冲区中的第一行。
D:删除模式空间的第一行
[root@ansible ~]# cat test02.txt
This is the header line.
This is a data line.
This is the last line.
[root@ansible ~]# sed '/^$/{N ; /header/D}' test02.txt
This is the header line.
This is a data line.
This is the last line.
d:清空模式空间
[root@localhost ~]# cat wjm
1
2
11
22
111
222
[root@localhost ~]# sed '/1/d' wjm
2
22
222
3、保持空间
用于临时存储数据的,可以和模拟空间数据相互复制,但是不能进行修改。
命令 | 含义 |
---|---|
h | 将模式空间的内容覆盖到保持空间内容 |
H | 将模式空间的内容追加到保持空间 |
g | 将保持空间的内容复制到模式空间中 |
G | 将保持空间的内容追加到模式空间中 |
x | 交换保持空间和模式空间的内容 |
演示:
h/G组合使用:
[root@ansible ~]# cat test01
1
2
11
22
111
222
[root@ansible ~]# sed '/1/{h;d};/2/{G}' test01
2
1
22
11
222
111
g/H组合使用
// 复制模式空间内容到保持空间,在将匹配到模式空间的内容追加到保持空间中。然后将保持空间的内容覆盖到模式空间中输出
[root@ansible ~]# cat test01
1
2
11
22
111
222
[root@ansible ~]# sed '/1/h;/2/H;g' test01
1
1
2
11
11
22
111
111
222
大小写字母转换
//小写字母转换为大写字母
[root@ansible ~]# cat test 01
find the Match statement
Consult the Get statement
Using the Read statement to retrieve data
[root@ansible ~]# cat sed
/the .* statement/{ //匹配包含这一段的行
h //匹配内容从模式空间覆盖到保持空间中
s/.*the (.*) statement.*/\1/ //将匹配到的行替换成整行
y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/ //转换命令将小写字母转换为大写字母,大转小调换一下位置即可
G //保存在保持空间中的行追加到模式空间
s/(.*)\n(.*the ).*( statement.*)/\2\1\3/
//排序,按照2.1.3顺序排列匹配到的内容 第一个小括号是1 第二个小括号是2...
}
[root@ansible ~]# sed -rf sed test 01
find the MATCH statement
Consult the GET statement
Using the READ statement to retrieve data
//第二行不转换大小字母
[root@ansible ~]# cat sed01
/the .* statement/{
/Get/b end
h
s/.*the (.*) statement.*/\1/
y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
G
s/(.*)\n(.*the ).*( statement.*)/\2\1\3/
:end
}
[root@ansible ~]# sed -rf sed01 test01
find the MATCH statement
Consult the Get statement
Using the READ statement to retrieve data
x:
将模式空间中的内容与保持空间中的内容进行互换交换
[root@ansible ~]# cat wjm
1
2
11
22
111
222
[root@ansible ~]# sed '/22/{x;p;x}' wjm
1
2
11
22
111
222
4、高级的流程控制命令
sed 程序的执行过程会从第一个脚本命令开始,一直执行到最后一个脚本命令(D 命令是个例外,它会强制 sed 返回到脚本的顶部,而不读取新的行)。sed 提供了 b 分支命令来改变命令脚本的执行流程,其结果与结构化编程类似。
分支命令格式:
Branch命令用于在脚本中将控制流转到另一行。
[address] [label]
address:决定在哪行或哪些行执行分支命令
label:参数定义于何处分支
address 参数决定了哪些行的数据会触发分支命令,label 参数定义了要跳转到的位置。
需要注意的是,如果没有加 label 参数,跳转命令会跳转到脚本的结尾,比如:
[root@ansible ~]# cat test02
This is the header line.
This is the first data line.
This is the second data line.
This is the last line.
[root@ansible ~]# sed '{2,3b ; s/This is/Is this/ ; s/line./test?/}' test02
Is this the header test?
This is the first data line.
This is the second data line.
Is this the last test?