三剑客-sed

sed 是Stream Editor(字符流编辑器)的缩写,简称流编辑器。什么是流?大家可以想象以下流水线,sed就像一个车间一样,文件中的每行字符都是原料,运到sed车间,然后经过一系列的加工处理,最后从流水线下来就变成货物了。

sed语法

sed 选项 命令 文件名或者管道符传递的输入

选项

image.png

命令

image.png

image.png

测试文件准备

image.png

在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的意思

image.png

image.png

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 <
image.png
  • 第一种 用sed在test.txt文件末尾增加三行,比如
    abcd
    efg
    hijk

sed '$a abcd\nefg\nhijk\n' test.txt

image.png
  • 第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 ~]$ 

image.png

i 指定行或者位置 插入内容

image.png

image.png

c 修改

image.png
image.png

image.png
  • 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 
image.png
[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


image.png
  • ! 对指定行以外的所有行应用命令
    特殊符号有如下这些
    image.png

image.png

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

image.png

如果要对文件实质性修改, 需要选项加 -i

image.png

指定行号进行替换

image.png

[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行进行替换

引用变量替换

image.png

分组替换()和\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'

image.png

案例:取出网卡为ens33的ip地址

image.png

上面结果合并写法
ifconfig ens33 | sed -nr '2s#^.*inet (.*) netmask.*$#\1#gp' 2表示第2行
image.png

扩展:用awk实现更简单如下


image.png

系统开机启动项优化

image.png

完成优化命令: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

image.png

案例 取出文件 person.txt的权限
查看文件权限: stat filename
方式一:用grep

image.png

方式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

image.png

方式3 :用 cut
stat person.txt |sed -n "4p"|cut -d "(" -f 2|cut -d '/' -f 1 cut分隔只能单个字符分隔

image.png

stat person.txt |sed -n "4p"| sed -nr 's#^.*\(0##gp'|sed -nr 's#/.*$##gp'
image.png

方式4 stat -c%a person.txt

image.png

案例批量重命名
数据准备:
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

image.png

查 p

image.png
  • 按单行查询


    image.png
  • 按多行范围查询


    image.png
image.png
  • 按步长查询


    image.png
  • 正则匹配


    image.png
image.png
  • 混合匹配


    image.png

    image.png
  • 过滤多个字符串
    image.png
  • -e 多个条件过滤 类似grep -e
    image.png

sed如何取不连续的行
sed -n '1p;3p;5p' filename 分号获取不连续的行

image.png

``
显示匹配字符串的行号

image.png

显示最后一行的行号
sed -n '$=' person.txt

image.png

练习题

拷贝 /etc/passwd 到当前目录

  1. 替换root为adeng888,只替换一次,与替换所有
    `sed -n 's#root#adeng88#1p' passwd

sed -n 's#root#adeng88#gp' passwd
`

  1. 替换前10行b开头的用户,改为C,且仅仅显示替换的结果
[root@hadoop100 adeng]# sed '1,10s/^b/C/1p' passwd -n #  1p的1表示只替换第一处
Cin:x:1:1:bin:/bin:/sbin/nologin

  1. 替换前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
  1. 删除4行后面所有
    image.png

    5.删除除root开始,到ftp之间的行
    sed '/^root/,/^ftp/d' passwd

准备文件lovers.txt

cat > lovers.txt <
  1. 将文件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]# 

image.png

正则匹配的时候需要注意,扩展正则我们要加 -r,否则匹配不到

  1. 跟文件前三行,添加@符号
    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.

  1. 匹配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

你可能感兴趣的:(三剑客-sed)