blueyi's notes

Follow Excellence,Success will chase you!

0%

Linux实用工具总结之sed

一些会比较经常用到的Linux下的工具,当然都是命令行。多数工具需要与正则表达式配合使用,所以可以很多工具使用前都需要先了解正则表达式,正则表达式可以参考这里正则表达式学习笔记

关于

sed是流编辑器,全称为stream editor,即sed可以直接处理管道传递来的命令,当然sed也支持直接处理文件。sed的处理单位为行,也就是说它会根据自己的参数对文件或流中的内容一行一行地进行处理,包含替换、删除、新增、获取特定行等。默认情况下sed处理的是文件的副本,如果要直接改写文件,需要使用选项参数-i。

sed的基本用法

sed [可选项] [命令模式] [文件名]

下面分别讲一下常用的可选项和常用的命令

可选项

-n--quiet, --silent静默输出
默认情况下sed会输出所有行,并在处理完一行之后立即输出被处理过之后的结果行,这就导致输出之后会多出我们并不需要的未处理的行。例如sed '/abc/p' ts.txt,这里我们使用sed只是进行匹配,并调用命令p输出,这样会输出ts.txt中的所有行,并将含abc的行多输出一次,如果想只输出被命令p处理的行。则使用-n选项,表示不显示处理过程,只输出被sed处理过的行。
-e后跟需要执行的命令模式
sed后面可以接多个-e指定的命令模式来进行连续处理。如:
将ts.txt中所有第5行到第7行中的第一个abc替换成cdf,并将所有行中的第一个love替换成LOVE,命令如下,暂时只需要知道命令s是替换的功能,跟vim中的s功能简直完全一样:
sed -e '5,7s/abc/cdf/' -e 's/love/LOVE/' ts.txt
更多内容参见下面的-f
-f 后跟一个含有命令模式的文件
sed从该文件加载命令模式来处理各行。默认情况下当不提供-e,-f选项时,sed命令后面的第一个非可选项(即以-开头)将被当成模式被执行。所以当不是需要同时顺序执行多个命令时,可以不用-e选项。
-r,--regexp-extended 表示采用扩展正则表达式
-i 表示直接在原文件中修改 这个应该是最重要的命令,因为默认情况下sed并不会修改原文件

命令

命令配合正则表达式组成的模式是sed的关键,命令模式的格式一般为“[address1],[address2] [command] [arguments]”
命令格式即可以使用单引号包括,也可以使用双引号,单引号和双引号可以配合使用,例如要匹配双引号时,可以'/"/',当然也可以使用转义\。用address来表示想要处理的行范围,当然如果省略所有address表示处理所有行,如果只有一个address,则表示只处理匹配到的这一行。address即可以是行号,也可以是通过正则表达式匹配到的行(sed处理的单位永远是行),例如从第3行到第6行应用命令d(表示删除):sed '3, 6d',或者删除从第一个含有abc的行开始到第一个含有xyz之间的行:sed '/abc/,/xyz/d'。而且address还支持相对位置,例如从第一个匹配行开始的后面连接5行输出:sed '/abc/, +5p'。sed命令中所有需要正则匹配的地方都是放在斜扛/之间。`

行内匹配并替换命令s

s命令非常常用(substitute),跟vim中的s功能几乎完全一样,
使用格式为sed '[addr1][,addr2]s/exp1/exp2/flag'
其中flag可以取g表示行内全局替换(即替换一行中的所有匹配的串)。或者接一个数字,表示替换一行中的第几个匹配到的串。或者接
字符p表示向标准输出打印结果(其实p也是一个单独的命令)
s命令支持使用分号;进行多个匹配处理,使用&表示匹配到的变量,$可以代表最后一行,正则表达式中圆括号匹配的内容可以被当成变量
下面举几个例子说明:
将所有行中的第一个abc替换为xyz:
sed 's/abc/xyz/' ts.txt

将第3行到第6行中的第2开始的abc替换成xyz并输出处理之后的结果行:
sed -n '3,6s/abc/xyz/p' ts.txt

在原文件中将从第一个含有ab1的行开始到第一个含有xy2的行中的所有my替换成MY:
sed -i '/ab1/,/xy2/s/my/MY/g' ts.txt

将从第8行开始到第一个含有abc的行中的第2个开始的my全部替换为your:
sed '8,/abc/s/my/your/2g' ts.txt

将1到3行中的abc替换成xyz,并去掉3行之后的所有abc:
sed 's/abc/xyz/g; 3,$s/abc//g' ts.txt
上述处理等价于两个-e的处理sed -e 's/abc/xyz/g' -e '3,$s/abc//g' ts.txt

将所有行中的abc使用圆括:
sed 's/abc/(&)/g' ts.txt

打印出html文件中所有除标签之外的行中内容:
sed -n 's/<[^>]*>//gp' ts.html

输出文件中所有含abc[n]和love[n]的行中的abc[n]和love[n]输出,并以:分隔:
sed -n 's/.*\(abc\d*\).*\(love\d*\).*/\1:\2/gp' ts.txt
注意匹配中的圆括号需要使用转义字符转义,表示其是正则表达式中的意义,后面使用\1,\2…来表示匹配到的变量

行替换命令c
用法与s类似,不过c命令是直接替换整行,而不是在行内进行替换,用法为:
sed '[addr1][,addr2]c string'表示将addr1到addr2行内容替换为string,注意这里不是将两个地址之间的各行替换为string,而是指一起替换为一行,但当为单一的正则匹配时,匹配多少行就替换多少行。
下面举例说明:
将3到8行替换为一行love:
nl ts.txt | sed '3,8c love'
前面的nl命令是为了显示行号。

将所有行替换为love:
sed 'c love' ts.txt

将所有含有abc的行替换为love:
sed '/abc/c love' ts.txt

行删除命令d

d与c的用法一样,只是它表示删除。
举一个例子吧:
删除所有空行:
sed '/^$/d' ts.txt

行插入命令ai
其中a表示在行后追加一行,i表示在行前追加一行。下面举例说明:
在第一行前插入hello,最后一行后插入world:
sed -e '1i hello' -e '$a world' ts.txt

在从含有abc的行开始到含有xyz的行之间的各行后插入一行hello:
sed '/abc/,/xyz/a hello' ts.txt

将读或追加下一行到缓冲区命令n与N

这两个命令可以直接理解为可用于交替处理各行,其中n处理偶数行,N处理奇数行。例如:
将所有偶数中的love换成LOVE,但奇数行不变:
sed 'n; s/love/LOVE/g' ts.txt

将从第一行开始的两行合并为一行:
sed -i 'N; s/\n//' ts.txt

打印命令p

p命令已经在s命令中使用过多次,用于向标准输出中打印sed处理的行,由于sed默认会显示处理过程,所以通常p与-n一起使用。例如:
显示从abc到xyz的所有行:
sed -n '/abc/,/xyz/p' ts.txt

输出从含有abc行开始的连续3行:
sed -n '/abc/, +3p' ts.txt

嵌套命令

sed支持对命令组合及嵌套使用,通过分号(;)实现多个命令组合使用,通过大括号({})实现命令嵌套,举例说明:
对1到3行执行命令/abc/d:
sed '1,3 {/abc/d}' ts.txt

对1到3行中含有abc且同时含有xyz的行删除:
sed '1,3 {/abc/{/xyz/d}}' ts.txt

对所有行匹配到abc则删除,匹配到空行则替换为love:
sed '/abc/d; s/^$/love/' ts.txt

sed的gnu官方手册:http://www.gnu.org/software/sed/manual/sed.html

Welcome to my other publishing channels