sed是一个流编辑工具,从文件或管道中读取输入流,以行为单位,对字符串进行一定的处理后输出处理结果。
sed命令基本格式如下:
sed <OPTIONS> <input-files>
sed -f script-file <input-files>
OPTIONS为sed命令的参数,不过这些参数可以放在一个文件script-file中,通过“-f script-file”指定即可,input-files为待处理的文件,可以是空格分隔的多个文件。先介绍几个有用的参数:
-n:禁止打印处理结果,不修改文件时(不使用“-i”)默认是会打印的。
-e script:不使用“-e”时,只能执行一个命令,如果想执行多个命令,就要在每个命令(script)前使用“-e”,这样就可以一次性执行多个命令而不出错。
-i[SUFFIX]:修改文件,若指定了SUFFIX,则对文件进行备份,备份文件名为文件名加后缀SUFFIX,默认是不修改文件的。
--follow-symlinks:修改符号文件时,连同指向的原文件一起修改,默认是不修改原文件只修改符号文件的,这样也就破坏了符号链接关系。
-l N:仅对命令“l”有效,指定每行打印的最多字符数,超过N时将使用续行符“\”进行换行。
--posix:禁用GNU扩展,sed命令的某些功能如“l width”为GNU扩展,禁用后再使用时将出错。
-r:扩展正则表达式,比如说花括号“{}”,否则要使用转义字符“\”进行转义。
-s:处理多个文件时,分别对待它们,否则这些文件被当作一个输入流,也可以理解为一个大文件,有可能达不到预期效果。
-u:输入、输出buffer尽可能小。
-z:行分隔符替换为空字符,多行文本犹如一行长文本。
sed涉及两个概念,命令和地址,有些命令需要指定地址,有些则不需要。地址即行号,下面是地址的用法:
number 一个数字,指定行号,第一行为1。
$ 最后一行。
first~step 匹配第first行及之后的每隔step行数的行。
addr1,+N 匹配addr1及紧随其后的N行。
addr1,~N 匹配addr1及紧随其后的直到行号为N的行,包括第N行。
first,last 匹配第first行与第last行之间的行,包括第first行和第last行。
/regexp/ 匹配与正则表达式regexp相符的行。
\CregexpC 匹配与正则表达式regexp相符的行,C为标记字符,可以是任意字符。
下面以例子说明sed命令的详细用法。
字符替换
1、“y/source/dest/”把文本行中与source中的各字符相同的字符逐渐替换为dest中的各字符,这意味着source与dest的字符个数必须相等,且替换是一一对应的,即source中的第n个字符替换为dest中的第n个字符。
$ echo "abc123abc123" | sed y/a1/x0/
xbc023xbc023
交换buffer与匹配行
2、“x”交换buffer与匹配的内容,如下例子中,buffer初始值为空,所以输出的第一行也为空,第二行为原文件的第一行,第三行为源文件的第二行。
$ cat script
x
$ cat file
1
2
3
$ sed -f script file
1
2
结果保存到文件
3、“w filename”把结果输出到文件filename,如下例子中,把文件file中的“1”替换为“x”,结果打印到屏幕的同时还保存到了文件output。
$ cat script
y/1/x/
w output
$ cat file
1
2
3
$ sed -f script file
x
2
3
$ cat output
x
2
3
正则替换字符串
4、“s/regexp/replacement/”把文本行中与正则表达式regexp匹配的内容替换为replacement,如下例子中,把“an”替换为“ONE”。
$ echo "this is an example" | sed s/an/ONE/
this is ONE example
下面是一个高级用法,符号“&”表示匹配到的内容,因为是特殊字符,所以需要转义或者使用“-r”,使用“-r”时需要单引号或双引号,例子中给“an”前后各添加一个短横线。
$ echo "this is an example" | sed s/an/-\&-/
this is -an- example
$ echo "this is an example" | sed -r "s/an/-&-/"
this is -an- example
$ echo "this is an example" | sed -r 's/an/-&-/'
this is -an- example
正则表达式可以使用圆括号进行分组,匹配到的内容用“\n”表示,n从1到9,表示圆括号的序号,如下例子中,正则表达式有4个分组,只显示与第3、4个分组匹配的内容。
$ echo "this is an example" | sed -r 's/(this) (is) (an) (example)/\3 \4/'
an example
行首、行尾添加内容:
$ echo "hello sed" | sed 's/^/xxx/'
xxxhello sed
$ echo "hello sed" | sed 's/$/xxx/'
hello sedxxx
打印匹配行
5、“p”打印匹配的内容,如下几个例子作了对比,默认打印匹配的内容和没有匹配的内容,“-n”禁止输出,同时使用“-n”和“p”则只打印匹配的内容。
$ cat file
1
2
3
$ sed s/1/x/ file
x
2
3
$ sed -n s/1/x/ file
$ sed -n s/1/x/p file
x
$ sed s/1/x/p file
x
x
2
3
处理下一行
6、“n”、“N”对于匹配的内容来说,前者读下一行,后者追加下一行,如下例子所示。
$ sed -e 's/1/x/' file
x
2
3
x1
22
33
$ sed -e n -e 's/1/x/' file
1
2
3
x1
22
33
$ sed -e N -e 's/1/x/' file
x
2
3
x1
22
33
特殊格式打印匹配行
7、“l”以一种特殊的格式显示各行,比如说添加行尾标记符。
$ cat file
1
2
3
$ sed l file
1$
1
2$
2
3$
3
$ sed -n l file
1$
2$
3$
buffer与匹配行
8、“h”、“H”、“g”、“G”分别表示复制匹配内容到buffer、追加匹配内容到buffer、复制buffer到匹配内容、追加buffer到匹配内容,如下例子所示,使用了“G”,buffer为空,每个匹配行后多了1个空行。
$ cat file
1
2
3
11
22
33
$ sed -n -e 's/1/x/p' file
x
x1
$ sed -n -e G -e 's/1/x/p' file
x
x1
删除行
9、“d”删除命令,如下例子所示。
$ cat file
1
2
3
11
22
33
$ sed 1d file
2
3
11
22
33
$ sed 1,5d file
33
替换行
10、“cXXX”用XXX替换整行内容,如下例子中,替换第2行为“===”。
$ cat file
1
2
3
11
22
33
$ sed 2c=== file
1
===
3
11
22
33
追加外部文本
11、“r filename”、“R filename”分别表示在每行后追加filename中的所有内容、在每行后追加filename中的一行(从filename中的第一行开始,依次读取第二行、第三行……),如下例子所示。
$ cat file
1
2
3
$ cat ext
123abc
======
$ sed -e 's/1/x/' file
x
2
3
$ sed -e 'r ext' -e 's/1/x/' file
x
123abc
======
2
123abc
======
3
123abc
======
$ sed -e 'R ext' -e 's/1/x/' file
x
123abc
2
======
3
插入行
12、“iXXX”行前插入内容为XXX的一行,如下例子所示,在第二行前插入“hellosed”。
$ cat file
1
2
3
$ sed 2ihellosed file
1
hellosed
2
3
追加行
13、“aXXX”行后追加内容为XXX的一行,如下例子所示,在第二行后追加“hellosed”。
$ cat file
1
2
3
$ sed 2ahellosed file
1
2
hellosed
3
打印行号
14、“=”打印行号,行号独立一行输出,如下例子所示。
$ cat file
hello
sed
$ sed = file
1
hello
2
sed
标签
15、使用冒号标记一个标签,然后使用“b”跳转到某个标签,类似于C的goto,直接看如下例子。
$ cat file
123456
123456
123456
$ cat script
:num1 s/1/x/
:num2 s/2/x/
:num3 s/3/x/
$ sed -f script file
xxx456
xxx456
xxx456
$ sed -e 'b' -f script file
123456
123456
123456
$ sed -e 'b num1' -f script file
xxx456
xxx456
xxx456
$ sed -e 'b num2' -f script file
1xx456
1xx456
1xx456
$ sed -e 'b num3' -f script file
12x456
12x456
12x456
$ sed -e 'b num4' -f script file
sed: can't find label for jump to `num4'
最后补充一下,命令“q”、“Q”表示立即终止sed执行,符号“#”为注释符,类似于shell的“#”、C/C++的“//”,命令可以放在一对花括号中。