Linux之sed进阶
1.sed &用法
1.1. sed & 用法
[root@ecs-76840553 sed]# cat 2 You are beautiful hello world hello alknlaknqlw hello hello hello world [root@ecs-76840553 sed]# cat 2| sed -r 's/hello/(&)/' You are beautiful (hello) world hello alknlaknqlw (hello) hello (hello) world [root@ecs-76840553 sed]# cat 2| sed -r 's/hello/(&)/g' You are beautiful (hello) world (hello) alknlaknqlw (hello) (hello) (hello) world [root@ecs-76840553 sed]#
讲解:& 符号代表的是你前面的匹配的内容。sed 是以行为单位的,默认匹配行的第一个,全部匹配需要加上g。
2.sed改变执行流程命令
2.1 sed b 命令
语法:
[address]b [label]
address 参数决定了哪些行的数据会触发分支命令,label 参数定义了要跳转到的位置。需要注意的是,如果没有加 label 参数,跳转命令会跳转到脚本的结尾。例如:
[root@ecs-76840553 sed]# cat lable.txt This is the header line. This is the first data line. This is the second data line. This is the last line. [root@ecs-76840553 sed]# sed '{2,3b; s/This is/Is this/ ; s/line./test?/}' lable.txt Is this the header test? This is the first data line. This is the second data line. Is this the last test? [root@ecs-76840553 sed]#
可以看到,因为 b 命令未指定 label 参数,因此数据流中的第2行和第3行并没有执行那两个替换命令。如果我们不想直接跳到脚本的结尾,可以为 b 命令指定一个标签(也就是格式中的 label,最多为 7 个字符长度)。在使用此该标签时,要以冒号开始(比如 :label2),并将其放到要跳过的脚本命令之后。这样,当 sed 命令匹配并处理该行文本时,会跳过标签之前所有的脚本命令,但会执行标签之后的脚本命令。
[root@ecs-76840553 sed]# sed -r '{2,3b lable s/This is/Is this/ ;:lable s/line./test?/}' lable.txt Is this the header test? This is the first data test? This is the second data test? Is this the last test? [root@ecs-76840553 sed]#
[root@ecs-76840553 sed]# sed -r '{/second/b lable s/This is/Is this/ ;:lable s/line./test?/}' lable.txt Is this the header test? Is this the first data test? This is the second data test? Is this the last test? [root@ecs-76840553 sed]# sed -r '{/three/b lable s/This is/Is this/ ;:lable s/line./test?/}' lable.txt Is this the header test? Is this the first data test? Is this the second data test? Is this the last test? [root@ecs-76840553 sed]#
在以上两个例子中,如果文本行中出现了 second,程序的执行会直接跳到 lable 标签之后的脚本行。如果分支命令的模式没有匹配three,sed 会继续执行所有的脚本命令。b 分支命令除了可以向后跳转,还可以向前跳转。
[root@ecs-76840553 sed]# echo "This, is, a, test, to, remove, commas." |sed -n '{:start; s/,//1p ;/,/b start}' This is, a, test, to, remove, commas. This is a, test, to, remove, commas. This is a test, to, remove, commas. This is a test to, remove, commas. This is a test to remove, commas. This is a test to remove commas. [root@ecs-76840553 sed]#
在这个例子中,当缓冲区中的行内容中有逗号时,脚本命令就会一直循环执行,每次迭代都会删除文本中的第一个逗号,并打印字符串,直至内容中没有逗号。
2.2 sed t 命令
类似于 b 分支命令,t 命令也可以用来改变 sed 脚本的执行流程。t 测试命令会根据 s 替换命令的结果,如果匹配并替换成功,则脚本的执行会跳转到指定的标签;反之,t 命令无效。测试命令使用与分支命令相同的格式:
[address]t [label]
[root@ecs-76840553 sed]# cat lable.txt | sed -r 's/first/two/;t tt; s/line/2222/;:tt' This is the header 2222. This is the two data line. This is the second data 2222. This is the last 2222. [root@ecs-76840553 sed]#
匹配不成功例子:
[root@ecs-76840553 sed]# cat lable.txt | sed -r 's/pipei/two/;t tt; s/line/2222/;:tt' This is the header 2222. This is the first data 2222. This is the second data 2222. This is the last 2222.
3.sed保持空间
sed 命令处理的是缓冲区中的内容,其实这里的缓冲区,应称为模式空间。值得一提的是,模式空间并不是 sed 命令保存文件的唯一空间。sed 还有另一块称为保持空间的缓冲区域,它可以用来临时存储一些数据。下表列出了 5 条可用来操作保持空间的命令。
命令 | 功能 |
h | 将模式空间中的内容复制到保持空间 |
H | 将模式空间中的内容附加到保持空间 |
g | 将保持空间中的内容复制到模式空间 |
G | 将保持空间中的内容附加到模式空间 |
x | 交换模式空间和保持空间中的内容 |
通常,在使用 h 或 H 命令将字符串移动到保持空间后,最终还要用 g、G 或 x 命令将保存的字符串移回模式空间。保持空间最直接的作用是,一旦我们将模式空间中所有的文件复制到保持空间中,就可以清空模式空间来加载其他要处理的文本内容。由于有两个缓冲区域,下面的例子中演示了如何用 h 和 g 命令来将数据在 sed 缓冲区之间移动。
[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 -n '/first/{h;p;n;p;g;p;}' data2.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 命令打印模式空间的当前内容,现在变回第一个数据行了。