Sed简介:

sed是stream editor的缩写,是一种在线编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,只是对存放在缓冲区里的行做处理,除非使用重定向存储输出。

语法是:sed [options] ‘{command}’ [filename]

定址:

通过定址来定位所需编辑的行,该地址用数字构成,用逗号分隔的两个行数表示以这两行为起止的行的范围(包括行数表示的那两行)。如1,3表示1,2,3行,美元符号($)表示最后一行。范围可以通过数据,正则表达式或者二者结合的方式确定 。

字符参数:

/sed/      匹配所有sed的行

^        行首定位符    /^sed/匹配所有以sed开头的行

$        行尾定位符    /sed$/匹配所有以sed结尾的行

.        匹配除换行符以外的单个字符    /s.d/匹配s后接一个任意字符,然后是d

*        匹配零个或多个前面出现的字符    /*sed/匹配所有模板是一个或多个字符后紧跟sed的行

[]       匹配指定字符组内的任一字符    /[Ss]ed/匹配sed和Sed

[^]      匹配不在指定字符组内的任一字符    /[^A-RT-Z]ed/匹配不包含A-R和T-Z的一个字母开头紧跟ed的行

\(..\)    保存已匹配的字符    s/\(love\)able/\1rs,loveable被替换成lovers

       \1代表被匹配到的第一个模式,\2代表被匹配到的第二个模式,以此类推,sed 一共可以记录9个模式,模式就是正则表达式用 () 扩起来的内容,例如这里的love

[root@Super svn]# echo "justin51cto"|sed 's/\([a-z]*\).*/\1/'
justin
[root@Super svn]# echo "justin51cto2018blog"|sed 's/\([a-z]*\)\([0-9]*\)/\2\1/'     
51justincto2018blog
[root@Super svn]# echo "justin51cto2018blog"|sed 's/\([a-z]*\)\([0-9]*b\)/\2\1/'
justin512018bctolog
[root@Super svn]#

      \1代表匹配到的部分第一个用()括起来的内容,\2代表第二个用()括起来的内容,

\<     词首定位符    /\

\>    词尾定位符    /love\>/匹配包含以love结尾的单词的行

x\{m\}    连续m个x    /0\{5\}/匹配包含5个o的行

x\{m,\}    至少m个x    /o\{5,\}/匹配至少有5个o的行

x\{m,n\}    至少m个,但不超过n个x    /o\{5,10\}/匹配5--10个o的行

[[:space:]]表示空格或者tab的集合

option:

-n      使用安静的模式,只有经过sed处理的那一行才会被列出来,否则要处理的那行会出现两次

[root@justin home]# cat sed.txt
1 2 2 2 3 4 5
2 2 2 2 3 4 5
3 2 2 2 3 4 5
4 3 4 4 9 2 2
[root@justin home]# sed '/^3/p' sed.txt
1 2 2 2 3 4 5
2 2 2 2 3 4 5
3 2 2 2 3 4 5
3 2 2 2 3 4 5
4 3 4 4 9 2 2
[root@justin home]# sed -n '/^3/p' sed.txt
3 2 2 2 3 4 5
[root@justin home]#

匹配以3开头的行并打印出来,p表示打印匹配的行,

[root@justin home]# sed -n '2p' sed.txt
2 2 2 2 3 4 5
[root@justin home]# sed -n '2,$p' sed.txt
2 2 2 2 3 4 5
3 2 2 2 3 4 5
4 3 4 4 9 2 2
[root@justin home]#

显示指定行内容

多条件匹配

-e    允许多个编辑同时进行,也可以用分号隔开。一般用”;”更为简洁,这里相当于或的关系,

[root@justin home]# sed -e '1,2d' -e '3s/2/8/g' sed.txt
3 8 8 8 3 4 5
4 3 4 4 9 2 2
[root@justin home]# sed  '1,2d;3s/2/8/g' sed.txt
3 8 8 8 3 4 5
4 3 4 4 9 2 2
[root@localhost ~]# sed -n '/\(ABCD\|1234\)/P' mul.txt 
ABCD1234
ab1234
abCD1234
[root@localhost ~]# cat mul.txt 
ABCD1234
ABC5678
ab1234
AB12
abCD1234
[root@localhost ~]# sed -n '/\(yes\|no\)/P' mul.txt

[root@Super ~]# sed -n '/GSSAPIAuthentication no/{/GSSAPIAuthentication yes/p}' sed.txt 
GSSAPIAuthentication no GSSAPIAuthentication yes
[root@localhost ~]# sed -n '/ABCD/{/1234/P}' mul.txt 
ABCD1234
[root@localhost ~]# cat mul.txt 
ABCD1234
ABCD5678
abcd1234
ABcd1234
abCD1234
[root@localhost ~]#


r filename    从文件中读取

[root@justin home]# cat sed1.txt
a
b c
d e f
[root@justin home]# sed '/^2/r sed1.txt' sed.txt
1 2 2 2 3 4 5
2 2 2 2 3 4 5
a
b c
d e f
3 2 2 2 3 4 5
4 3 4 4 9 2 2
[root@justin home]#

读取sed1.txt文件,并显示在sed.txt中匹配2开头行之后

w filename   写入数据

[root@justin home]# sed '/^2/w sed1.txt' sed.txt
1 2 2 2 3 4 5
2 2 2 2 3 4 5
3 2 2 2 3 4 5
4 3 4 4 9 2 2
[root@justin home]# cat sed1.txt
2 2 2 2 3 4 5
[root@justin home]#

将sed.txt中匹配2开头的行,并写入到sed1.txt中

-i        直接修改文件内容,而不屏幕输出

将nrpe.cfg里面第221行中的check_hda1全部替换成/check_disk_root,/dev/hda1全部替换成/dev/sda3

  sed -i '221s/check_hda1/check_disk_root/g;221s?/dev/hda1?/dev/sda3?g' /usr/local/nagios/etc/nrpe.cfg

 sed当中使用变量替换,sed命令使用双引号的情况下,使用$var直接引用

#!/bin/bash
ROOTPATH=`df -Th|grep /$|awk '{print $1}'`
sed -i "221s?/dev/sda3?$ROOTPATH?g" /usr/local/nagios/etc/nrpe.cfg
#sed -i '221s?/dev/sda3?'"$ROOTPATH"'?g' /usr/local/nagios/etc/nrpe.cfg

第二条命令$ROOTPATH里面的是双引号,外面的是单引号

-f       直接sed的动作写在一个文件中,-f filename则可以执行filename内的sed动作

-r     Sed 使用扩展正则

常用command:

i     在当前行之前插入文本, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);

[root@justin home]# sed '/^1/i adfdf\ndddd' sed.txt
adfdf
dddd
1 2 2 2 3 4 5
2 2 2 2 3 4 5
3 2 2 2 3 4 5
4 3 4 4 9 2 2
[root@justin home]#

在匹配行前加入一行 

[root@localhost ~]# sed -i '/tcp --dport 80 -j ACCEPT/i\-A INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT' /etc/sysconfig/iptables
[root@localhost ~]# cat /etc/sysconfig/iptables
...
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
....
[root@localhost ~]#

     sed -i '/tcp --dport 80 -j ACCEPT/i\-A INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT' /etc/sysconfig/iptables

     i\ 中的\可以替换成空格

     sed -i '/tcp --dport 80 -j ACCEPT/i -A INPUT -m state --state NEW -m tcp -p tcp --dport 8090 -j ACCEPT' /etc/sysconfig/iptables

a     在当前行下一行加入一行文本,

[root@justin home]# sed '1a test' sed.txt
1 2 2 2 3 4 5
test
2 2 2 2 3 4 5
3 2 2 2 3 4 5
4 3 4 4 9 2 2
[root@justin home]# sed '1,3a test' sed.txt
1 2 2 2 3 4 5
test
2 2 2 2 3 4 5
test
3 2 2 2 3 4 5
test
4 3 4 4 9 2 2
[root@justin home]# sed '1a test\ntest1' sed.txt
1 2 2 2 3 4 5
test
test1
2 2 2 2 3 4 5
3 2 2 2 3 4 5
4 3 4 4 9 2 2
[root@justin home]# sed '1a test\ntest1\ntest2' sed.txt
1 2 2 2 3 4 5
test
test1
test2
2 2 2 2 3 4 5
3 2 2 2 3 4 5
4 3 4 4 9 2 2
[root@localhost ~]#

在匹配行后加入一行 

[root@localhost ~]# sed -i '/tcp --dport 80 -j ACCEPT/a\-A INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT' /etc/sysconfig/iptables
[root@localhost ~]# cat /etc/sysconfig/iptables 
...
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 5901 -j ACCEPT
...
[root@localhost ~]#


在最后一行加入一行 

[root@localhost ~]# sed -i '$a\TMOUT=1800' /etc/profile

c     取代, c 的后面可以接字串,这些字串可以取代匹配的行!

[root@justin home]# sed '1c Hi' sed.txt
Hi
2 2 2 2 3 4 5
3 2 2 2 3 4 5
4 3 4 4 9 2 2
[root@justin home]# sed '1,3c Hi' sed.txt
Hi
4 3 4 4 9 2 2
[root@justin home]# cat /opt/mongodb4/mongodb-linux-x86_64-3.4.6/conf/mongod.conf
bind_ip = 127.0.0.1
[root@justin home]# sed -i '/^bind_ip/cbind_ip = 0.0.0.0' /opt/mongodb4/mongodb-linux-x86_64-3.4.6/conf/mongod.conf 
[root@justin home]# cat /opt/mongodb4/mongodb-linux-x86_64-3.4.6/conf/mongod.conf
bind_ip = 0.0.0.0
[root@justin home]#

s     替换,格式:sed 's/要替换的字符串/新的字符串/g' (要替换的字符串可以用正则表达式),三根斜线中间是替换的样式,命令中的三根斜线分隔符可以换成别的符号,例如换成问号”?”:sed 's?原字符串?替换字符串?',这里的替换用法类似前面提到的vim里的替换

替换样式可以多个在同一条命令中执行,用分号”;”分隔,例如:

sed 's/^/添加的头部&/g;s/$/&添加的尾部/g' //同时执行两个替换规则

[root@justin home]# sed -n '2s/2/3/p' sed.txt   ;第二行的第一个2替换为3,并打印出来
3 2 2 2 3 4 5
[root@justin home]# sed -n '2s/2/3/gp' sed.txt   ;第二行的2全部替换为3,并打印出来,g为全部替换
3 3 3 3 3 4 5
[root@justin home]# sed -n 's/2/3/gp' sed.txt    ;将所有行的2替换为3
1 3 3 3 3 4 5
3 3 3 3 3 4 5
3 3 3 3 3 4 5
4 3 4 4 9 3 3
[root@justin home]# sed -n '1s/2/3/p;3s/2/7/gp' sed.txt  ;第一行的第一个2替换为3,第三行2全部替换为7
1 3 2 2 3 4 5
3 7 7 7 3 4 5
[root@justin home]# sed -n '2,3s/3/9/p' sed1.txt   ;第2、3行的第一个3替换为9
9 1 3 2 4 3 6 7
9 1 3 2 3 4 5 6
[root@justin home]# sed -i '2s?^?# chkconfig: 2345 10 90\n# description:Tomcat service\nCATALINA_HOME=/app/apache-tomcat-7.0.61\nJAVA_HOME=/app/jdk1.7.0_79?' /etc/init.d/tomcat

s前面的数字表示要匹配的行号,不写默认为全部匹配,g表示全部,如果没有g标记,则只有每行第一个匹配的,“\n”表示换行

[root@justin home]# sed -n '2s/2/3/3p' sed.txt
2 2 3 2 3 4 5
[root@justin home]#

匹配指定的字符串的行替换

[root@localhost app]# cat sed.txt 
1 justin blog 123 justin justin
2 justin blog 345 51cto justin
3 justin blog abc justin justin
[root@localhost app]# sed '/345/ s/51cto/justin/g' sed.txt 
1 justin blog 123 justin justin
2 justin blog 345 justin justin
3 justin blog abc justin justin
[root@localhost app]#

指定行到匹配的字符串的行替换

[root@localhost app]# cat sed.txt 
1 justin blog 345 justin justin
2 justin blog 345 51cto justin
3 justin blog abc justin justin
[root@localhost app]# sed '2,/justin/ s/justin/51cto/g' sed.txt 
1 justin blog 345 justin justin
2 51cto blog 345 51cto 51cto
3 51cto blog abc 51cto 51cto
[root@localhost app]#

从第2行到匹配到justin的行的区间的justin替换成51cto


& 符号代表的是你前面的匹配的模式

[root@localhost app]# echo "justin blog"|sed 's/[a-z]*/(&)/'
(justin) blog
[root@localhost app]#

sed默认匹配第一个。如果需要把blog 也加上 () 那么就需要加上 g (global)参数。

[root@localhost app]# echo "justin blog"|sed 's/[a-z]*/(&)/g'
(justin) (blog)
[root@localhost ~]# echo -e "111814054\n111812092\n101473011" |sed "s/[[:digit:]]*/'&',/g"  替换带单引号
'111814054',
'111812092',
'101473011',
[root@localhost ~]# echo -e "111814054\n111812092\n101473011" |sed "s/[[:digit:]]*/'&',/g"|sed ':a;N;$!ba;s/\(.*\),/\1/'   去掉最后一个逗号
'111814054',
'111812092',
'101473011'
[root@localhost ~]#

:a;N;$!ba预读入全部内容至pattern space然后只替换最后一个逗号


如果只匹配第二个呢

[root@localhost app]# echo "justin blog"|sed 's/[a-z]*/(&)/2'
justin (blog)
[root@localhost app]#

如果是第2个及其后面的

[root@localhost app]# echo "justin blog address"|sed 's/[a-z]*/(&)/2g'
justin (blog) (address)
[root@localhost app]# cat sed.txt 
1 justin blog justin justin justin
2 justin blog justin justin justin
3 justin blog justin justin justin
[root@localhost app]# sed '2s/justin/51cto/g' < sed.txt > output.txt 
[root@localhost app]# cat sed.txt 
1 justin blog justin justin justin
2 justin blog justin justin justin
3 justin blog justin justin justin
[root@localhost app]# cat output.txt 
1 justin blog justin justin justin
2 51cto blog 51cto 51cto 51cto
3 justin blog justin justin justin
[root@localhost app]#

p前面的数字3为要把第几个2匹配为3,这里p前面的数字是针对匹配的行而言,

[root@localhost src]# cat sed
1 2 3 4 5 6
1 2 2 2 3 3
2 3 4 3 2 5
[root@localhost src]# sed -n 's/2/a/2p' sed
1 2 a 2 3 3
2 3 4 3 a 5
[root@localhost src]#


[root@justin home]# sed -n '/9/s/3/5/gp' sed.txt
4 5 4 4 9 2 2
[root@justin home]#

匹配有9的行,然后把改行的3替换为5

sed ‘s/\(.*\)old/\1new/’ filename 替换每行的最后1个”old”为”new”

[root@justin home]# sed -n '/9/!s/3/5/gp' sed.txt
1 2 2 2 5 4 5
2 2 2 2 5 4 5
5 2 2 2 5 4 5
[root@justin home]# sed -n '/^2/!p' sed.txt
1 2 2 2 3 4 5
3 2 2 2 3 4 5
4 3 4 4 9 2 2
[root@justin home]#

感叹号表示不匹配感叹号之前的条件


y 字元的替换

[root@localhost app]# echo "hello"|sed 'y/hello/justi/'
jussi
[root@localhost app]#

h替换成j,e替换成u,l替换成s,o替换成i,这里替换前后的长度要一致,相同的字符以第一次匹配到的为准,例如这里的l


d    删除行

[root@justin home]# sed '/5$/ d' sed.txt
4 3 4 4 9 2 2
[root@justin home]#

删除末尾为5的行

[root@justin ~]# cat /etc/samba/smb.conf |egrep -v '#|;'|sed '/^[[:space:]]*$/d'

[root@justin home]# cat /etc/samba/smb.conf |sed '/^*$/d'|egrep -v '#|;'

删除空白行,[[:space:]]表示空格或者tab的集合,[[:space:]]后面跟着一个*,表示匹配0个或多个空格或者tab。[[:space:]]可以用/s表示

[root@justin home]# sed '1d' sed.txt
2 2 2 2 3 4 5
3 2 2 2 3 4 5
4 3 4 4 9 2 2
[root@justin home]# sed '2,3d' sed.txt
1 2 2 2 3 4 5
4 3 4 4 9 2 2
[root@justin home]# sed '3,$d' sed.txt

删除指定行

[root@localhost app]# cat sed.txt 
1 2 3
# 1 2 3
* 1 2 3
a b c
# a b c
* a b d
1 2 a b
[root@localhost app]# sed '/#/d' sed.txt 
1 2 3
* 1 2 3
a b c
* a b d
1 2 a b
[root@localhost app]# sed '/#/!d' sed.txt   #删除除了含有#行以外的行
# 1 2 3
# a b c
[root@localhost app]#

删除匹配的行

[root@localhost app]# sed '/# 1/,/* a/d' sed.txt #删除从含有# 1到含有* a区间的行
1 2 3
1 2 a b
[root@localhost app]# cat sed.txt 
1 2 3
# 1 2 3
* 1 2 3
a b c
# a b c
* a b d
1 2 a b
[root@localhost app]# sed '/# a/,3d' sed.txt 
1 2 3
# 1 2 3
* 1 2 3
a b c
* a b d
1 2 a b
[root@localhost app]#


w    将匹配的输一局写入其他文件

[root@justin home]# touch sed2.txt
[root@justin home]# sed -n '2,3 w sed2.txt' sed.txt
[root@justin home]# cat sed2.txt
2 2 2 2 3 4 5
3 2 2 2 3 4 5
[root@justin home]#

p     打印,将某个选择的资料打印出来。通常 p 会与参数 sed -n 一起运作

Tips:

行后增加一行空行:[root@justin home]# sed G sed.txt

RHEL6基础三十六之服务器维护基础命令⑥sed、tr、tee_第1张图片

行后增加两行空行:[root@justin home]# sed 'G;G' sed.txt

RHEL6基础三十六之服务器维护基础命令⑥sed、tr、tee_第2张图片

倒置所有行,第一行成为最后一行[root@justin home]#  sed -n ’1!G;h;$p’ filename或是sed ’1!G;h;$!d’ filename

wKiom1LTgGLjuICJAADP2R9Q5Vc922.jpg

filename每两行合并成一行[root@justin home]# sed ‘$!N;s/\n/ /’ filenamewKioL1LTgT3ws8uCAADfTKo6h34657.jpg

删除文件中相邻的重复行[root@justin home]# sed ‘$!N; /^\(.*\)\n\1$/!P; D’


tr  转换或者删除字符

tr [OPTION]... SET1 [SET2]

tr指令从标准输入设备读取数据,通过替换或删除操作进行字符转换,输出到标准输出设备。可以用一个字符来替换另一个字符,或者可以完全除去一些字符,可以用它来除去重复字符。使用tr时要转换两个字符串:字符串1用于查询,字符串2用于处理各种转换。tr刚执行时,字符串1中的字符被映射到字符串2中的字符,然后转换操作开始。


不带参数:将SET1中的每个字符替换SET2中的每个字符,字符是顺序替换,如果SET1的字符长度大于SET2,那么将SET1中多出来的字符用SET2中的最后一个字符替换。如果SET1的字符长度小于SET2,那么只将SET1中多出的字符不做替换

[root@localhost ~]# echo abcdabcd|tr 'abc' '12'
122d122d
[root@localhost ~]# echo abcdabcd|tr 'abc' '12345'
123d123d
[root@localhost ~]#

所有的a被替换成1,所有b被替换成2,所有多出的c、d被替换成set2中的最后一个数字2


-t:将SET2中的每个字符替换SET1中的每个字符,字符字符顺序1对1替换,无论SET1还是SET2哪个长,只替换对应的字符,多出的不替换。

[root@localhost ~]# echo abcdabcd|tr -t 'abc' '12'
12cd12cd
[root@localhost ~]# echo abcdabcd|tr -t 'abc' '12345'
123d123d
[root@localhost ~]#



-d:删除SET1中指定的字符,这里没有SET2

[root@localhost ~]# echo abcdabcd|tr -d 'c'
abdabd
[root@localhost ~]# echo ABCabc|tr -d '[:lower:]'
ABC
[root@localhost ~]#

-s:将SET1中指定的连续的连续重复的字符用单个字符替代,可以使用-s '\n'删除空行。

[root@localhost ~]# echo AABCBaabbc|tr -s '[:lower:]'
AABCBabc
[root@localhost ~]# echo AABCBaabbc|tr -s 'A'
ABCBaabbc
[root@localhost ~]#

-c:取反操作,取数据流中SET1中指定字符的补集。也就是符合 SET1 的部份不做处理,不符合的剩余部份才进行转换,通常与-d配合使用

[root@localhost ~]# echo AABCBaabbc|tr -dc 'A'
AA[root@localhost ~]# echo AABCBaabbc|tr -dc 'A \n'
AA
[root@localhost ~]#



tee   将数据重定向到文件和屏幕上

tee (选项) (参数)

-a:向文件中重定向时使用追加模式;

-i:忽略中断(interrupt)信号。

[root@localhost ~]# ls | tee 1.txt
acl
anaconda-ks.cfg
sed
substr.txt
[root@localhost ~]# cat 1.txt 
acl
anaconda-ks.cfg
sed
substr.txt
[root@localhost ~]# ls /root/| tee -a 1.txt
1.txt
acl
anaconda-ks.cfg
sed
substr.txt
[root@localhost ~]# cat 1.txt 
acl
anaconda-ks.cfg
sed
substr.txt
1.txt
acl
anaconda-ks.cfg
sed
substr.txt
[root@localhost ~]#