【sed】进阶
sed的基本用法已能满足大多数需求,但当需要时,知道这些高级特效的存在及如何使用将提供莫大的帮助!
1. 多行命令
sed编辑器提供三个用于处理多行文本的特殊命令:
-
N:将数据流的下一行加入当前模式空间
-
D:删除多行组中的一行
-
P:打印多行组中的一行
【next命令】
单行next命令:
小写的n命令,将下一行文本移入模式空间(工作空间)并挤走已有文本,即跳过当前行进入下一行。
1 # cat data1.txt 2 this is the header line 3 4 this is the data line 5 6 this is the last line
经n命令处理后可跳过第一行:
1 # sed '/header/{n;d}' data1.txt 2 this is the header line 3 this is the data line 4 5 this is the last line
多行next命令:
大写的N命令,将下一行文本并入当前模式空间,即加到已有文本之后。两个文本行合并成一行,仍以换行符分隔。
1 # cat data2.txt 2 This is the header line. 3 This is the first data line. 4 This is the second data line. 5 This is the last line.
经N命令处理后:
1 # sed '/first/{N;s/\n/ /}' data2.txt 2 This is the header line. 3 This is the first data line. This is the second data line. 4 This is the last line.
Tips:使用N命令可查找分散在两行的文本。注意最后一行进入模式空间,执行N命令由于没有后续的可读入行,会导致后面的命令无法执行。
【多行删除命令】
单行删除命令d和N命令一起使用时,会将模式空间的文本全部删除;
多行删除命令D,只删除模式空间的第一行,即删除到换行符为止的所有字符(包含换行符)。
1 # cat data5.txt 2 3 This is the header line. 4 This is a data line. 5 6 This is the last line.
1 # sed '/^$/{N ; /header/D}' data5.txt 2 This is the header line. 3 This is a data line. 4 5 This is the last line.
Tips:这种办法可实现删除特殊行,比如需要同时满足两种条件的行。
【多行打印命令】
单行打印命令会打印出模式空间内的所有文本;
多行打印命令仅打印多行模式空间的第一行,即打印换行符之前的所有字符。
1 # sed -n '/header/{N;P}' data5.txt 2 This is the header line.
2. 保持空间
sed编辑器除了模式空间(patten space)外,还有一个保持空间(hold space)。处理模式空间的某些行时,可以使用保持空间临时保存一些行。
命令
|
描述
|
h
H
g
G
x
|
将模式空间复制到保持空间
将模式空间附加到保持空间
将保持空间复制到模式空间
将保持空间附加到模式空间
交换模式空间和保持空间
|
读懂以下命令,理解保持空间用法:
1 # sed -n '/first/ {h ; p ; n ; p ; g ; p }' data2.txt 2 This is the first data line. 3 This is the second data line. 4 This is the first data line.
3. 排除命令
感叹号命令(!)用于排除某个命令,即让原本的命令不起作用。
1 # sed -n '/header/p' data2.txt 2 This is the header line.
普通p命令打印匹配文本行,使用!后,效果相反,不打印该行而打印其它行:
1 # sed -n '/header/!p' data2.txt 2 This is the first data line. 3 This is the second data line. 4 This is the last line.
结合保持空间反转文本行的顺序:
1 # sed -n '{1!G ; h ; $p }' data2.txt 2 This is the last line. 3 This is the second data line. 4 This is the first data line. 5 This is the header line.
Tips:sed编辑器默认会将命令循环应用在每一行文本上,因此合理使用命令,可写出简洁高效的sed脚本
4. 改变流
sed编辑器提供了改变脚本执行流程的方法。
【分支】
分支(branch)命令(b)可只对数据流中的特定行执行命令。
格式:
[address]b [label]
address参数定义触发分支的行数,label参数用于定义要跳转的位置。若没有加label,则会跳过脚本。
加address,不加label,跳过后面所有脚本:
1 # sed '{2,3b ; s/This is/Is this/ ; s/line./test?/}' data2.txt 2 Is this the header test? 3 This is the first data line. 4 This is the second data line. 5 Is this the last test?
加address,加label,分支匹配处的行跳到标签处,执行标签后的命令;不匹配的行执行所有命令:
1 # sed '/first/b jump1 ; s/This is the/No jump on/; :jump1 ; s/This is the/Jump here on/' data2.txt 2 No jump on header line. 3 Jump here on first data line. 4 No jump on second data line. 5 No jump on last line.
不加address,b命令无条件跳转到标签上,可造成循环的效果:
1 # echo "This, is, a, test, to, remove, commas." | sed -n '{:start;s/,//1p;b start}' 2 This is, a, test, to, remove, commas. 3 This is a, test, to, remove, commas. 4 This is a test, to, remove, commas. 5 This is a test to, remove, commas. 6 This is a test to remove, commas. 7 This is a test to remove commas. 8 ^C
该脚本不会停止循环,可使用/,/b start代替b start,在没有逗号时自动结束循环。
【测试】
测试(test)命令(t)会根据替换(s)命令的结果来跳转到某个标签。
不加label,跳过后面所有命令:
1 # sed 's/first/matched/; t ; s/This/Here/' data2.txt 2 Here is the header line. 3 This is the matched data line. 4 Here is the second data line. 5 Here is the last line.
加label,跳转到label处:
1 # echo "This,is,a,test,to,remove,commas." | sed -n '{:start ; s/,/ /p ; t start}' 2 This is,a,test,to,remove,commas. 3 This is a,test,to,remove,commas. 4 This is a test,to,remove,commas. 5 This is a test to,remove,commas. 6 This is a test to remove,commas. 7 This is a test to remove commas.
1 # sed 's/first/matched/; t ;s/This/Here/;s/line/LINE/' data2.txt 2 Here is the header LINE. 3 This is the matched data line. 4 Here is the second data LINE. 5 Here is the last LINE.
1 # sed 's/first/matched/; t jump ;s/This/Here/; :jump ;s/line/LINE/' data2.txt 2 Here is the header LINE. 3 This is the matched data LINE. 4 Here is the second data LINE. 5 Here is the last LINE.
Tips:使用标签和t命令可在脚本命令中形成循环
5. 模式替代
【&符号】
&符号可以提取命令中匹配模式中的全部文本。
1 # echo "The cat sleeps in his hat." | sed 's/.at/"&"/g' 2 The "cat" sleeps in his "hat".
【替代单独的单词】
用圆括号来定义子模式,在替换模式中用\1等引用子模式,可提取匹配模式中的部分文本。
1 # echo 1234567 | sed ':start;s/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;t start' 2 1,234,567
Tips:圆括号必须转义
6. 重定向sed输出
【 $() 】
默认情况,sed会将脚本结果输出到STDOUT,可使用$()将输出保持到变量中。和变量替换一样