9.4 9.5 sed

9.4 sed(上)

​9.4 9.5 sed_sed

  • 其实grep工具的功能还不够强大,它实现的只是查找功能,而不能把查找的内容替换。以前用vim操作文档的时候,可以查找也可以替换,但只限于在文本内部操作,而不能输出到屏幕上。

  • sed工具就能把替换的文本输出到屏幕上,而且还有其他更丰富的功能。sed和awk都是流式编辑器,是针对文档的行来操作的。


准备工作,把~/grep/passwd 复制到 ~/sed/tset.txt

mkdir sed
cd sed/
ls
cp ../grep/passwd test.txt
ls


sed -n 'n'p filename

'n'是一个数字,表示第几行。

-n作用是只显示我们要打印的行,无关紧要的内容不显示。

p=print 打印


打印第二行的数据(-n是把除了第二行之外的数据都不被打印出来):

sed -n '2'p test.txt 
bin:x:1:1:bin:/bin:/sbin/nologin

指定范围用法,例如 第二到第五行

sed -n '2,5'p test.txt 
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
123:rao
456:r>o

第五到最后一行25,$

sed -n '25,$'p test.txt 
chrony:x:998:996::/var/lib/chrony:/sbin/nologin
aming:x:1000:1000::/home/aming:/bin/bash
user1:x:1001:1001::/home/user1:/bin/bash
user5:x:1002:1002::/home/user5:/bin/bash

打印全部行

sed -n '1,$'p test.txt

打印某个字符串的行,例如打印含有root的行

sed -n '/root/'p test.txt 
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

同样也支持特殊符号用法,如^ $ . + *等等

但是有些特殊符号需要脱义,例如+需要用\脱义。在sed里,可以用-r脱义。

sed -n '/o\+t/'p test.txt 
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
123:rooot
sed -nr '/o+t/'p test.txt 
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
123:rooot

匹配2次o的行

sed -nr '/o{2}/'p test.txt 
root:x:0:0:root:/root:/bin/bash
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
321:hooome
123:rooot
456:hooooooo
postfix:x:89:89::/var/spool/postfix:/sbin/nologin

-e用法 实现多个动作(支持数据重叠)

例如,在同一条命令上 指定行打印 匹配字符串打印。

打印第二行,且匹配'bus'的字符串 示例如何:

sed -e '2'p -e '/bus/'p -n test.txt 
bin:x:1:1:bin:/bin:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin


9.5 sed(下)


-I 不区分大小写

sed '/bus/'Ip -n  test.txt 
132:r1o:BUs
dbus:x:81:81:System message bus:/:/sbin/nologin

-d 删除指定的行

这里的删除指的是删除显示,而不是真正修改文件的内容。

wc -l test.txt
29 test.txt
sed '1,25'd test.txt
aming:x:1000:1000::/home/aming:/bin/bash
user1:x:1001:1001::/home/user1:/bin/bash
user5:x:1002:1002::/home/user5:/bin/bash

先备份test.txt,复制备份为test.txt.bak

cp test.txt test.txt.bak
ls
test.txt  test.txt.bak

-i 直接修改文件的内容 

能把文件内容删掉,也就是说能完全修改文件内容。

wc -l test.txt
29 test.txt
sed -i '1,25'd test.txt
wc -l test.txt
4 test.txt

删除指定含有字符串的行

删除含有user5的行

cat test.txt
aming:x:1000:1000::/home/aming:/bin/bash
user1:x:1001:1001::/home/user1:/bin/bash
user5:x:1002:1002::/home/user5:/bin/bash
sed -i '/user5/'d test.txt
cat test.txt
aming:x:1000:1000::/home/aming:/bin/bash
user1:x:1001:1001::/home/user1:/bin/bash

把备份复制回来

sed的替换功能 

其实sed的替换功能跟vim的替换功能用法差不多,格式也是'1,10s/root/toor/g',其中s是替换,g是全局替换。

sed '1,10s/root/toor/g' test.txt |head
toor:x:0:0:toor:/toor:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
123:rao
456:r>o
132:r1o:BUs
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

因为有+,所以在sed上面要-r脱义。

其中这里的ro+等于roo,因为在正则表达式里面,此条件是成立的。

sed -r '1,10s/ro+/r/g' test.txt
sed -r '1,10s/ro+/r/g' test.txt |head 
rt:x:0:0:rt:/rt:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
123:rao
456:r>o
132:r1o:BUs
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown


sed支持管道| 调换位置

把root和bin/bash调换位置,

:是分隔符

[root@centos7 sed]# head test.txt |sed -r 's/([^:]+):(.*):([^:]+)/\3:\2:\1/'

's/  不指定换位,默认从第一行开始。

([^:]) 非:的字符

(.*):  .*代表贪婪匹配,(.*):贪婪匹配:  

\3:\2:\1 代表每个: 反序的意思代指最后跟最前调换位置.

前面()()() 后面\\\表示

​9.4 9.5 sed_sed_02

head test.txt |sed -r 's/([^:]+):(.*):([^:]+)/\3:\2:\1/'
/bin/bash:x:0:0:root:/root:root
/sbin/nologin:x:1:1:bin:/bin:bin
/sbin/nologin:x:2:2:daemon:/sbin:daemon
123:rao
456:r>o
BUs:r1o:132
/sbin/nologin:x:3:4:adm:/var/adm:adm
/sbin/nologin:x:4:7:lp:/var/spool/lpd:lp
/bin/sync:x:5:0:sync:/sbin:sync
/sbin/shutdown:x:6:0:shutdown:/sbin:shutdown

把所有英文字母的信息删除掉

head test.txt |sed 's/[a-zA-Z]//g' 
::0:0::/://
::1:1::/://
::2:2::/://
123:
456:>
132:1:
::3:4:://://
::4:7::///://
::5:0::/://
::6:0::/://

如果替换的时候/后为空,表示空白,就是删除的意思。

在所有行前面加入aaa 

&表示后面的数据

head test.txt |sed -r 's/(.*)/aaa:&/'
aaa:root:x:0:0:root:/root:/bin/bash
aaa:bin:x:1:1:bin:/bin:/sbin/nologin
aaa:daemon:x:2:2:daemon:/sbin:/sbin/nologin
aaa:123:rao
aaa:456:r>o
aaa:132:r1o:BUs
aaa:adm:x:3:4:adm:/var/adm:/sbin/nologin
aaa:lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
aaa:sync:x:5:0:sync:/sbin:/bin/sync
aaa:shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown