sed -stream editor for filtering and transforming text
sed作为一个流编辑器,默认情况下作用于所有行,也可以指定行地址来限定sed命令要操作的行,sed的一般命令形式如下:
[address] command
这个行地址可以是一个由’/’限定的正则表达式或者使用文本行号。多数sed命令接受由两个地址行限定的一个范围,但也有一些命令只能接受单行的地址。当需要选定范围时,用逗号连接两个地址。Sed允许多个命令同时作用于同一地址行,需要用大括号将这多个命令包含起来:
address{
[address_1] command1
[address_2] command2
……
}
对于第一条命令的位置没有限制,它可以和左大括号位于同一行,但是右大括号必须自己单独一行, 且每一个命令都可以有自己的地址行。
当使用行号寻址时,’$’代表了文件的最后一行的位置:
sed ‘1,100s/pattern/replacement/’ file /*限制在前100行替换*/
sed ‘100, $s/pattern/replacement/’ file /*在100行之后替换*/
sed -e '1,/start/s/pattern/replacement/' -e '/stop/,$ s/pattern/replacement/'/*使用数字和patterns结合定界*/
接下来介绍一些sed常用的基本命令:
替换
语法:[address]s/pattern/replacement/flags
替换命令作用于地址行,如果行地址没有提供,它将作用与所有的输入行,sed将会用replacement来替换pattern匹配的内容。
flags的值可为:
n: 1~512, 标示替换仅在第n个匹配处生效.
g: 全局匹配替换. 当一行中有多个匹配,默认情况下只在一个匹配处替换; 可以使用定界符’g’来进行全局匹配替换. 将数字’n’与’g’一起使用,可以实现从第n个匹配处开始全局替换
p: 打印匹配内容。默认情况下sed将打印读入的每一行,如果有替换发生,它会打印替换的新行,如果使用’p’ sed会重复打印替换的新行。一般与 ’-n’ 选项连用,’-n’ 会屏蔽掉打印输出,此时sed只打印出发生过替换的行。
w:写匹配到文件
将修改的行写到指定文件中:
$ echo -e "abc\nbcd\ncde" | sed -n 's/b/B/w b.txt'
$ cat b.txt
aBc
Bcd
也可以直接指定写入的行:
$ echo -e "abc\nbcd\ncde" | sed -n '1,2 w b.txt'
$ cat b.txt
abc
bcd
I: 使得匹配模式对于大小写不敏感
$ echo -e "one One oNe ONe ONE" | sed 's/one/GET/Ig'
GETGET GET GET GET
如果指定了行地址,且行地址为一正则表达式,但是替换命令而没有提供匹配模式字符串,此时行地址表达式将被用作匹配模式:
$echo "<al:moAttribute>" |sed '/al/ s//soap/'
<soap:moAttribute>
对于行地址要求使用’/’进行限定,但是对于替换命令表达式可以使用除换行符外的其它任何符号进行限定。当pattern内包含了定界符’/’时,可以选定其它的符号作为限定符。(也可以使用’\’进行转义),注意定界符三个为一组。
$ echo "/usr/local/bin:/usr/bin" | sed's/\/usr\/local\/bin/\/common\/bin/'
/common/bin:/usr/bin
或使用’:’作为定界符:
$ echo "/usr/local/bin:/usr/bin" | sed's:/usr/local/bin:/common/bin:'
/common/bin:/usr/bin
替换字符串(replacement)用来取代匹配到的模式串(pattern),替换字符转中可以包含以下几种特殊字符:
&: 代替pattern匹配的字符串。 在replacement里使用匹配到的子串,对于正则匹配不能知道的匹配的具体字符,使用’&’它就代表了匹配项内容
$ echo "Section 12.4" | sed 's/Section[1-9][0-9]?\.[1-9][0-9]?/(&)/'
Section12.4
\n: 代替匹配到的第n个子串,子串匹配模式可以用\( \)限定。 如:\(sub_pattern\)用来分隔pattern,’\1’ 标记了匹配的第一个部分子串,’\2’标记了匹配的第二个部分子串… sed命令可以最多标记到9个部分子串。
$ echo "first:second" | sed 's/\(.*\):\(.*\)/\2:\1/'
second:first
\: 可以用来转义’&’符,”\”符以及替换命令的分隔符。它也可以用在替换字符转中转义新行,从而可以将替换字符转转化为一个多行的,如:
$ echo"<al:moAttribute>" | sed '/al/ {
s/al/\
soap/
s/$/\
/
}
'
< #New liene
soap:moAttribute> #Replcement
#New line
$
删除
删除命令d会删除寻址模式匹配的行,如果没有寻址匹配的话会删除所有的行:
sed ‘3 d’ file /*删除第三行*/
sed ‘1,/^$/ d’file /*删除文件起始所有的空白行*/
添加、改变、插入行操作
sed允许向数据流中插入,附加和修改文本行:
语法: sed ‘[address] command \
new_line’
命令a在/pattern/匹配的行后追加新行,命令i在/pattern/匹配的行前插入新行,命令c改变/pattern/匹配的行。
$echo -e "Larry:\nPaul:" | sed '/Larry/ a\
Haier Road, QD
'
Larry:
Haier Road, QD
Paul:
打印行号
语法:[line-address] =
行地址后面接着’=’可以打印匹配的行号:
$echo -e "Larry:\nPaul:" | sed '/Larry/ {
=
a\
Haier Rd, QD
}'
1
Larry:
Haier Rd, QD
Paul:
读取下一行
语法:[address] n
该命令会输出当前的匹配行并直接读取下一行处理并没有
$echo -e "Larry:\nPaul:" | sed '/Larry/ {
> n
> a\
> Haier Rd, QD
> }'
Larry:
Paul:
Haier Rd, QD
读写文件
语法:[line-address]r file
[address]w file
读文件命令不能不能作用于一个地址范围,应该是一个行地址。写文件可直接将匹配到的地址行写到文件中。
$ cat a
.Ah XComment
.Bh YComment
.Ch ZComment
$ cat b.txt
.Dh AddComments
.Bh AddComments
$ sed -e '/Bh/r b.txt' -e '/Bh/d' a
.Ah XComment
.Dh AddComments
.Bh AddComments
.Ch ZComment
退出
语法: [line-address] q
退出操作只能作用于一个行地址上:
sed ’11, q’ /*11行的时候退出*/
sed 选项
-i —— 将改动保存到源文件中:
$ sed -i ‘s/pattern/replacement/’file
sed -i.tmp‘s/pattern/replacement/’file /*保存源文件到file.tmp*/
-e —— 将多个命令用一个sed进程处理,在每一个命令前加'-e' option:
$ echo -e "one" |sed -e 's/a/A/' -e's/e/E/' -e 's/i/I/' -e 's/o/O/' -e 's/u/U/'
OnE
也可以这样:
$ echo -e "one" |sed -e 's/a/A/;s/e/E/; s/i/I/; s/o/O/; s/u/U/'
OnE
-f —— 当有大量的sed 命令要执行时,可以将他们放到一个文件中并使用'-f' option:
$ echo 'one' | sed -f cc.txt
OnE
$ cat cc.txt
s/a/A/g
s/e/E/g
s/i/I/g
s/o/O/g
s/u/U/g