sed 是Stream Editor(字符流编辑器)的缩写,简称流编辑器。什么是流?大家可以想象以下流水线,sed就像一个车间一样,文件中的每行字符都是原料,运到sed车间,然后经过一系列的加工处理,最后从流水线下来就变成货物了。
sed语法
sed 选项 命令 文件名或者管道符传递的输入
选项
命令
测试文件准备
在adeng目录创建一个person.txt文件,指定内容如下:
101,chensiqi,CEO
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
cat >person.txt<
命令说明:使用一条cat命令创建多行文本,文件包含上面的内容,后面的操作都会使用这个文件
增
1. 单行增加,a后面增加的内容我们一般用空格区分。
sed '2a 106,dandan,CSO' person.txt
2a
2表示第2行 a表示追加 append的意思
2.多行增
准备创建一个test.txt文件,文件内容如下:
welcome to my blog.http://www.cnblogs.com/adenggag/
此行是空行
if you like my blog's contents,pls support me.
此行是空行
此行是空行
此行是空行
bye!boys and girls.
执行命令
cat > test.txt <
- 第一种 用sed在test.txt文件末尾增加三行,比如
abcd
efg
hijk
sed '$a abcd\nefg\nhijk\n' test.txt
- 第2种,用cat >>文件名<
[adeng@hadoop100 ~]$ cat >>test.txt < abcd
> efg
> hijk
> EOF
[adeng@hadoop100 ~]$ cat test.txt
welcome to my blog.http://www.cnblogs.com/adenggag/
if you like my blog\'s contents,pls support me.
bye!boys and girls.
abcd
efg
hijk
[adeng@hadoop100 ~]$
i 指定行或者位置 插入内容
c 修改
删
sed 'd' person.txt
如果在sed命令前面不指定地址范围,那么默认会匹配所有行,然后使用d命令删除功能就会删除这个文件的所有内容
[adeng@hadoop100 ~]$ cat person.txt
101,chensiqi,CEO
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
[adeng@hadoop100 ~]$ sed "2d" person.txt
101,chensiqi,CEO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
[adeng@hadoop100 ~]$ sed "2,4d" person.txt
101,chensiqi,CEO
105,feixue,CIO
[adeng@hadoop100 ~]$ sed "1~2d" person.txt
102,zhangyang,CTO
104,yy,CFO
[adeng@hadoop100 ~]$ sed "1,+2d" person.txt
[adeng@hadoop100 ~]$
[adeng@hadoop100 ~]$ cat person.txt
101,chensiqi,CEO
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
[adeng@hadoop100 ~]$ sed '2,$d' person.txt
101,chensiqi,CEO
[adeng@hadoop100 ~]$ sed '/CFO/d' person.txt
101,chensiqi,CEO
102,zhangyang,CTO
103,Alex,COO
105,feixue,CIO
[adeng@hadoop100 ~]$ sed '2,/104/d' person.txt
101,chensiqi,CEO
105,feixue,CIO
[adeng@hadoop100 ~]$ sed '/Alex/,2d' person.txt
101,chensiqi,CEO
102,zhangyang,CTO
104,yy,CFO
105,feixue,CIO
-
! 对指定行以外的所有行应用命令
特殊符号有如下这些
sed -n '/chensiqi/!p' person.txt
!p
表示不打印
[adeng@hadoop100 ~]$ cat person.txt
101,chensiqi,CEO
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
[adeng@hadoop100 ~]$ sed -n '/chensiqi/p' person.txt
101,chensiqi,CEO
[adeng@hadoop100 ~]$ sed -n '/chensiqi/!p' person.txt # 表示chensiqi以外的行都打印
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
改
如果要对文件实质性修改, 需要选项加 -i
指定行号进行替换
[adeng@hadoop100 ~]$ sed -i 's/adeng/chensiqi/g' person.txt #还原配置
[adeng@hadoop100 ~]$ cat person.txt
101,chensiqi,CEO
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
[adeng@hadoop100 ~]$ sed '3s#0#9#g' person.txt # 这里的3是 第3行 位置
101,chensiqi,CEO
102,zhangyang,CTO
193,Alex,COO
104,yy,CFO
105,feixue,CIO
前面学习的例子在sed命令“s”前没有指定地址范围,因此默认是对所有行进行操作。
而这个案例要求只将第3行的0换成9,这里就用到了我们前面学过的地址范围知识,在sed命令“s”前加上“3”就代表对第3行进行替换
引用变量替换
分组替换()和\1
sed软件的()的功能可以记住正则表达式的一部分,其中,\1为第一个记住的模式即第一个小括号中的匹配内容,\2第二个记住的模式,即第二个小括号中的匹配内容,sed最多可以记住9个
例如:echo "my name is adeng boy" 我只想保留adeng
echo "my name is adeng boy" | sed -r 's#^.*is (.*) .*$#\1#g'
案例:取出网卡为ens33的ip地址
上面结果合并写法
ifconfig ens33 | sed -nr '2s#^.*inet (.*) netmask.*$#\1#gp'
2表示第2行
扩展:用awk实现更简单如下
系统开机启动项优化
完成优化命令:systemctl list-unit-files|egrep -v "sshd|crond|rsyslog|sysstat|network"| awk '{print $1}'| sed -r 's#^(.*)#systemctl disable \1#g' |bash
awk优化开机启动:systemctl list-unit-files|egrep -v "sshd|crond|rsyslog|sysstat|network"| awk '{print "systemctl","disable",$1}'|bash
案例 取出文件 person.txt的权限
查看文件权限: stat filename
方式一:用grep
方式2:用
sed
stat person.txt |sed -n "4p"|sed -r 's#^.*\(0(.*)/-.*$#\1#g'
[adeng@hadoop100 ~]$ stat person.txt |sed -n "4p"
权限:(0664/-rw-rw-r--) Uid:( 1000/ adeng) Gid:( 1000/ adeng)
[adeng@hadoop100 ~]$ stat person.txt |sed -n "4p"|sed -r 's#^.*\(0(.*)/-.*$#\1#g'
664
方式3 :用 cut
stat person.txt |sed -n "4p"|cut -d "(" -f 2|cut -d '/' -f 1
cut分隔只能单个字符分隔
stat person.txt |sed -n "4p"| sed -nr 's#^.*\(0##gp'|sed -nr 's#/.*$##gp'
方式4 stat -c%a person.txt
案例批量重命名
数据准备:
touch stu_{1..10..2}_finished.txt
[adeng@hadoop100 ~]$ touch stu_{1..10..2}_finished.txt
[adeng@hadoop100 ~]$ ls
person.txt stu_1_finished.txt stu_3_finished.txt stu_5_finished.txt stu_7_finished.txt stu_9_finished.txt test1.txt test.txt
要求_finished.txt的文件去掉_finished。如 tu_1_finished.txt --》 tu_1.txt
[root@hadoop100 adeng]#
[root@hadoop100 adeng]# find ./ -name "*_finished.txt"
./stu_1_finished.txt
./stu_3_finished.txt
./stu_5_finished.txt
./stu_7_finished.txt
./stu_9_finished.txt
[root@hadoop100 adeng]# find ./ -name "*_finished.txt" | sed -r 's/(^.*)(_finished)(.*$)/\1\3/g'
./stu_1.txt
./stu_3.txt
./stu_5.txt
./stu_7.txt
./stu_9.txt
[root@hadoop100 adeng]# find ./ -name "*_finished.txt" | sed -r 's/(^.*)(_finished)(.*$)/mv & \1\3/g'
mv ./stu_1_finished.txt ./stu_1.txt
mv ./stu_3_finished.txt ./stu_3.txt
mv ./stu_5_finished.txt ./stu_5.txt
mv ./stu_7_finished.txt ./stu_7.txt
mv ./stu_9_finished.txt ./stu_9.txt
[root@hadoop100 adeng]# find ./ -name "*_finished.txt" | sed -r 's/(^.*)(_finished)(.*$)/mv & \1\3/g' |bash
[root@hadoop100 adeng]# ls
person.txt stu_1.txt stu_3.txt stu_5.txt stu_7.txt stu_9.txt test.txt test1.txt
查 p
-
按单行查询
-
按多行范围查询
-
按步长查询
-
正则匹配
-
混合匹配
- 过滤多个字符串
-
-e
多个条件过滤 类似grep -e
sed如何取不连续的行
sed -n '1p;3p;5p' filename
分号获取不连续的行
``
显示匹配字符串的行号
显示最后一行的行号
sed -n '$=' person.txt
练习题
拷贝 /etc/passwd 到当前目录
- 替换root为adeng888,只替换一次,与替换所有
`sed -n 's#root#adeng88#1p' passwd
sed -n 's#root#adeng88#gp' passwd
`
- 替换前10行b开头的用户,改为C,且仅仅显示替换的结果
[root@hadoop100 adeng]# sed '1,10s/^b/C/1p' passwd -n # 1p的1表示只替换第一处
Cin:x:1:1:bin:/bin:/sbin/nologin
- 替换前10行b开头的用户,改为C,切将m开头的行,改为M,且仅仅显示替换的结果
[root@hadoop100 adeng]# sed -n -e '1,10s#^b#C#1p' -e 's#^m#M#1p' passwd
Cin:x:1:1:bin:/bin:/sbin/nologin
Mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
- 删除4行后面所有
5.删除除root开始,到ftp之间的行
sed '/^root/,/^ftp/d' passwd
准备文件lovers.txt
cat > lovers.txt <
- 将文件lovers.txt中空白字符开头的行,添加注释符
sed -rn 's/(^\s.*$)|(^$)/#\1/gp' lovers.txt
或者
sed -rn -e 's/(^ .*$)/#\1/gp' -e 's/(^$)/#\1/gp' lovers.txt
空行也要考虑
7.删除文件的空行和注释行
sed -r '/^$|^#/d' lovers.txt
sed -e '/^$/d' -e '/^#/d' lovers.txt
sed '/^$/d;/^#/d' lovers.txt
这是-e
的简写,用分号分隔
[root@hadoop100 adeng]# sed -e '/^$/d' -e '/^#/d' lovers.txt
I like my lover.
I love my lover.
He likes his lovers.
[root@hadoop100 adeng]# cat lovers.txt
I like my lover.
I love my lover.
He likes his lovers.
#He loves his lovers.
#she lovers her cat
[root@hadoop100 adeng]# sed '/^$/d;/^#/d' lovers.txt
I like my lover.
I love my lover.
He likes his lovers.
[root@hadoop100 adeng]# sed -r '/^$|^#/d' lovers.txt
I like my lover.
I love my lover.
He likes his lovers.
[root@hadoop100 adeng]#
正则匹配的时候需要注意,扩展正则我们要加 -r,否则匹配不到
- 跟文件前三行,添加@符号
sed -nr '1,3s/(^.*$)/@\1/gp' lovers.txt
[root@hadoop100 adeng]# sed -nr '1,3s/(^.)/@\1/gp' lovers.txt
@ I like my lover.
@I love my lover.
@He likes his lovers.
- 匹配ens33的IP 地址
[root@hadoop100 adeng]# ifconfig ens33
ens33: flags=4163 mtu 1500
inet 192.168.37.100 netmask 255.255.255.0 broadcast 192.168.37.255
inet6 fe80::91ee:903d:a709:53b6 prefixlen 64 scopeid 0x20
ether 00:0c:29:51:97:1e txqueuelen 1000 (Ethernet)
RX packets 28867 bytes 2787290 (2.6 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 14560 bytes 1767219 (1.6 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@hadoop100 adeng]# ifconfig ens33|sed -rn '2s/^.*inet (.*) netmask.*$/\1/gp'
192.168.37.100
10.找出系统的版本
cat /etc/centos-release| sed -nr 's/.* ([1-9]).*$/\1/gp'
cat /etc/centos-release| sed -r 's/^.*release *([^.]).*$/\1/g'
[root@hadoop100 adeng]# cat /etc/system-release
CentOS Linux release 7.9.2009 (Core)
[root@hadoop100 adeng]# cat /etc/centos-release| sed -nr 's/.* ([1-9]).*$/\1/gp'
7
[root@hadoop100 adeng]#
[root@hadoop100 adeng]# cat /etc/centos-release
CentOS Linux release 7.9.2009 (Core)
[root@hadoop100 adeng]# cat /etc/centos-release| sed -r 's/^.*release *([^.]).*$/\1/g'
7