本文章参考《Linux大棚命令百篇》,推荐买着看,很好的一本书。
sed (stream editor)被称之为流编辑器。
sed命令是针对于行处理的工具,对每一行进行处理,并将处理的结果输出到标准输出。
sed的命令格式:
sed command file
command部分:针对每行的内容要进行的处理
file部分:要处理的文件,如果忽略file参数,则sed会把标准输入作为处理对象。
sed的工作原理:
sed会一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出
一个简单的栗子:
# cat example.txt
test 1
test2
testtest
XtestX
BBtest
# sed '/2/d' example.txt
test 1
testtest
XtestX
BBtest
这个栗子是删除文件中包含字符"2"的行。命令要用单引号括起来!
/2/d中的d表示删除,意思就是说只要某行含有字符2,则删除之。
想实现类似于cut -d : -f 1 /etc/passwd的效果,用sed怎么做呢?
# head -n 5 /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
# head -n 5 /etc/passwd | sed 's/:.*$//'
root
bin
daemon
adm
lp
一些命令
sed会将模式空间里的行经过处理后输出到标准输出,这是默认的处理方式。就是说,除非你使用d命令来删除此行,否则它无论变成什么样子,无论它被替换成什么形状,它都会多多少少被输出到屏幕上。
-n选项一般会和-p配合使用,意思是输出那些匹配到的行。
# cat example.txt
test 1
test2
testtest
XtestX
BBtest
# sed -n '/test2/p' example.txt
test2
sed的command部分可以分为两块:一块是范围设定,一块是动作处理。
范围设定可以采用两种不同的方式来表达:
- 指定行数:比如'3,5',表示第3行,4行,5行;而'5,$'表示第5行至文件最后一行。
- 匹配模式:例如/[dD]/表示匹配行首不是以d或D开头的行等等。
动作部分:
d:表示删除行
p:打印该行
r:读取指定文件的内容
w:写入指定文件
a:在下面插入新行新内容
看一下例子吧:
显示文件的第10到20行:
# sed -n '10,20p' example.txt
vfinj
VBFNJ
VFEANKM
VREF
VERFD
VF
BTERS F
3RQEVAF
BQTAW SV
Qreafd
qVWAD
将所有以V或v开头的行的所有小写n变为大写N
# sed '/^[vv]/s/n/N/g' example.txt
我们在command命令部分采用 /AA/s/BB/CC/g 的语法,这表示我们要匹配到文件中带有AA的行,并且将这些行中的BB替换成CC。
删除每行最后两个字符:
# sed 's/..$//' example.txt
删除每一行的前两个字符:
# sed ‘s/..//’ test
&符号的妙用:
&表示“被匹配的部分”
# cat mysed.txt
Beijing
London
# sed 's/Bei/&2008/' mysed.txt
Bei2008jing
London
更好的定位方法:
# cat mysed.txt
Beijing 2003
Beijing 2004
Beijing 2005
Beijing 2006
Beijing 2007
Beijing 2008
Beijing 2007
# sed -n '/2005/,/2007/p' mysed.txt
Beijing 2005
Beijing 2006
Beijing 2007
我们使用/2005/来匹配行范围的首行,用/2008/来匹配行范围的最尾行。可以看到,在匹配尾行时,只要遇到符合要求的行,即停止,不会再继续向后匹配了。(只是匹配到第一个2007,并没有匹配到第二个2007)
使用-e选项来设置多个command:
当包含超过一个的command的时候,必须在每个command前面加上选项-e
# sed -n -e '1,2p' -e '4p' mysed.txt
Beijing 2003
Beijing 2004
Beijing 2006
注意:-e后面必须立即接command,不允许再夹杂其他的选项
使用 -f指定command文件:
如果你的command很长,那么可以将其写在文件里,然后使用-f来设定这个文件作为command部分:
# cat callsed
/2004/,/2006/p
# sed -n -f callsed mysed.txt
Beijing 2004
Beijing 2005
Beijing 2006
插入和控制
在多个command之间,是按照在命令中的先后顺序来执行的。
插入内容:
将要插入的内容保存到一个单独的文件
$ cat ins.txt
====China====
使用r 实现插入
sed ‘/2005/r ins.txt’ mysed.txt
除了可以通过指定文件来插入外,还可以使用 'a'在特定行的下面插入特定内容:
# sed '/2004/a\china' mysed.txt
Beijing 2003
Beijing 2004
china
Beijing 2005
Beijing 2006
Beijing 2007
Beijing 2008
Beijing 2007
还可以使用 '\i'在指定行的上面添加内容:
# sed '/2004/i\china' mysed.txt
Beijing 2003
china
Beijing 2004
Beijing 2005
Beijing 2006
Beijing 2007
Beijing 2008
Beijing 2007
y动作:
y就是按照字符顺序,实现前后的替换
# sed 'y/ei/ie/' mysed.txt
Biejeng 2003
Biejeng 2004
Biejeng 2005
Biejeng 2006
Biejeng 2007
Biejeng 2008
Biejeng 2007
y的语法格式: y/source/dest/
如果source中出现了重复的字符,则只有第一次对应的替换会产生效果,后面的不会起作用。
原文
# cat mysed.txt
Beijing 2003
Beijing 2004
Beijing 2005
Beijing 2006
Beijing 2007
Beijing 2008
Beijing 2007
在iji到iba的替换中,只有j到b起到了作用
# sed 'y/iji/iba/' mysed.txt
Beibing 2003
Beibing 2004
Beibing 2005
Beibing 2006
Beibing 2007
Beibing 2008
Beibing 2007
对匹配行的下一行进行处理:
# sed '/2004/{n;y/eijing/EIJING/;}' mysed.txt
Beijing 2003
Beijing 2004
BEIJING 2005
Beijing 2006
Beijing 2007
Beijing 2008
Beijing 2007
这个例子就是找含有2004的行,然后将它下面的一行中的eijng替换为大写的EIJNG。这里面的“n;”起到了“移至下一行”的作用。n背后的含义其实是将下一行放到模式空间中去。
将指定行写入到指定文件中:
w动作会将匹配到的内容保存到另一个文件中:
# sed '/200[4-6]/w new.txt' mysed.txt
# cat new.txt
Beijing 2004
Beijing 2005
Beijing 2006
如果想在原文件中进行操作,需要加 -i 选项。