目录
3.5.8 sed -f 指定命令来对第二个文件的行进行处理
一、sed简介
sed 即 Stream EDitor,和 vim 不同,sed是行编辑器
sed是一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,
称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,
把缓冲区的内容送往屏幕。
接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。
Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等
二、sed 流编辑器的工作过程
sed的工作流程主要包括读取、执行和显示三个过程:
- 读取: sed从输入流 (文件、管道、标准输入) 中读取一行内容并存储到临时的缓冲区中(又称模式空间,pattern space )。
- 执行: 默认情况下,所有的sed命令都在模式空间中顺序地执行,除非指定了行的地址,否则sed命令将会在所有的行上依次执行。
- 显示: 发送修改后的内容到输出流。在发送数据后,模式空间将会被清空。在所有的文件内容都被处理完成之前,上述过程将重复执行,直至所有内容被处理完。
在所有的文件内容都被处理完成之前,上述过程将重复执行,直至所有内容被处理完。
注意:默认情况下所有的sed命令都是在模式空间内执行的,
因此输入的文件并不会发生任何变化,除非使用"sed -i"修改源文件、或使用重定向输出到新的文件中。
三、sed命令
3.1 基本格式
sed -e '操作' 文件1 文件2
sed -e '操作' 文件1 文件2
sed -f 脚本文件 文件1 文件2
sed -i -e '操作' 文件1 文件2
3.2 执行多条命令的格式
方式一:
sed -e '操作1' -e '操作2' 文件
sed -n -e '/^r/p' -e '/^b/p' /etc/passwd
方式二:
sed -e '操作1;操作2' 文件
3.3 常用选项
选项 | 说明 |
-e 或--expression= | 表示用指定命令来处理输入的文本文件,只有一个操作命令时可省略,一般在执行多个操作命令使用 |
-f 或--file= | 表示用指定的脚本文件来处理输入的文本文件 |
-h 或--help | 显示帮助 |
-i | 直接修改目标文本文件 慎用 |
-n | 仅显示script处理后的结果 |
3.4 常用操作符
操作符 | 说明 |
s | 替换,替换指定字符 |
d | 删除,删除选定的行 |
a | 增加,在当前行下面插入一行指定内容 |
i | 插入,在选定行上面插入一行指定内容 |
c | 替换,将选定行替换为指定内容 |
y | 字符转换,转换前后的字符长度必须相同 |
p | 打印,如果同时指定行,表示打印指定行;如果不指定行,则表示打印所有内容;如果有非打印字符,则以 ASCII 码输出。其通常与“-n”选项一起使用。 |
= | 打印行号 |
l | 打印数据流中的文本和不可打印的ASCII字符(比如结束符$、制表符\t) |
r | 扩展正则表达式 |
sed最为核心的功能是增删改查
3.5 sed命令打印功能
[root@localhost ~]#sed '' /etc/fstab #查看文件内容
[root@localhost opt]# sed '' < /etc/fstab #可以支持重定向输入
[root@localhost opt]# cat /etc/passwd |sed '' #也可以支持管道符
[root@shell 98]# sed '' /etc/fstab #查看文件内容
#
# /etc/fstab
# Created by anaconda on Mon Jul 29 18:29:03 2024
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/centos-root / xfs defaults 0 0
UUID=9eefb0bb-b2b5-45a2-bf1f-031a954cae18 /boot xfs defaults 0 0
/dev/mapper/centos-swap swap swap defaults 0 0
3.5.1 默认打印方式
[root@www rh]# sed -e 'p' test1.txt --sed有一个默认输出,加上P,会打印两行
123
123
345
345
789
789
000
000
[root@www rh]# sed -n 'p' test1.txt ---n禁止了默认输出,就只有一行
123
345
789
000
仅打印第几行
[root@shell 98]# ifconfig ens33 | sed -n '2p' #打印第二行
inet 192.168.23.10 netmask 255.255.255.0 broadcast 192.168.23.255
打印时对行号的操作
[root@shell 98]# sed -n '=' 1.txt #只显示行号
1
2
3
4
5
6
7
8
9
10
[root@shell 98]# cat 1.txt
123
123
435
234
54
574
54
54
54
[root@shell 98]# sed -n '=;p' 1.txt ---显示行号和每行的内容
1
123
2
123
3
435
4
234
5
54
6
574
7
54
8
54
9
54
10
3.5.2 sed命令的寻址打印
方式一:按照行号寻求内容
[root@localhost sed]#sed -n '1p' test1.txt --打印第一行
[root@localhost sed]#sed -n '4p' test1.txt --打印第四行
[root@localhost sed]#sed -n '$p' test1.txt --打印最后一行
方式二:进行行号范围区间的打印
[root@localhost sed]#sed -n '1,3p' test1.txt --打印1-3行
[root@localhost sed]#sed -n '5,$p' test1.txt --打印第五行到最后一行
[root@localhost sed]#sed -n '2,+2p' test1.txt ---打印第二行+两行的内容,相当于2,4p
[root@localhost opt]#sed -n '3p;5p' test1.txt ---输出第三行和第五行
[root@shell 98]# sed -n '1,+3p' 1.txt #打印第一行再加三行 相当于1,4
123
123
435
234
方式三:指定间隔打印
[root@localhost sed]#sed -n -e '2p' -e'$p' test1.txt ---打印第二行和最后一行
[root@localhost sed]#sed -n -e '2p' -e'3p' test1.txt ---打印第二行和第三行
方式四:对奇数行和偶数行的打印
[root@localhost sed]#sed -n 'n;p' test1.txt ---打印偶数的行
[root@localhost sed]#sed -n 'p;n' test1.txt ---打印奇数的行
n在p前面,跳过一行,打印下一行,就是偶数行;在后面,就是打印第一行,然后跳过一行,形成奇数行
3.5.3 文本模式过滤行内容
方式一:对包含的字符串进行过滤打印
[root@localhost sed]#sed -n '/o/p' test1.txt ---包含o的所有行
[root@localhost sed]#sed -n '/th/p' test1.txt ---包含th的所有行
方式二:应用基础正则表达式进行打印
[root@localhost sed]#sed -n '/^root/p' /etc/passwd --以root为开头的所有内容,全文本搜索
[root@localhost sed]#sed -n '/bash$/p' /etc/passwd --以bash结尾的所有内容,全文本搜索
[root@localhost sed]#sed -n '4,/bash$/p' /etc/passwd --从第四行开始,一直打印到第一个以bash为结尾的所在行
方式三:使用扩展正则表达式进行打印
注意:
sed -r 支持扩展正则表达式。同时在 使用{n}、{n,}、{n,m}时,括号{}前不需要加反斜杠\ 。
[root@localhost sed]# sed -r -n '/(99:){2,}/p' /etc/passwd ---包含有两个99:的内容所在行
[root@localhost sed]# sed -r -n '/^root|bash$/p' /etc/passwd ---包换以root开头,或者以bsah结尾的内容所在行
3.5.4 sed的删除操作
sed -i 时会对文本进行实际操作(建议对目标文件先进行备份,再进行操作)
通过行号进行删除
[root@localhost sed]#sed 'd' test1.txt ---删除所有,什么也不打印
[root@localhost sed]#sed -n '3d;p' test1.txt ---删除第三行,打印剩余的所有内容
[root@localhost sed]#sed -n '5,8d;p' test1.txt ---删除5到8行,打印剩余的所有内容
[root@localhost sed]#sed -n '5,$d;p' test1.txt ---删除5到最后一行行,打印剩余的所有内容
[root@localhost sed]#sed '4,6!d' test1.txt ---除了4-6行,其他的全部删除
如果要生效:sed -i -n
匹配字符串内容删除
[root@localhost sed]#sed '/one/d' test1.txt ---删除包含one的行
[root@localhost sed]#sed '/one/,/six/d' test1.txt ---删除one-six的行
[root@localhost sed]#sed '/one/,/six/!d' test1.txt ---除了one-six的行,其余的全部删除,反向删除
[root@localhost sed]#sed '/six/!d' test1.txt ---除了six的行,其余的全部删除,反向删除
字符串搭配正则进行删除:
[root@localhost sed]#sed '/^$/d' test1.txt ---通过^$,来删除空行;
删除空行的三种方法:
grep -v "^$" test1.txt ----过滤出非空行
cat test1.txt |tr -s "\n" ----压缩换行符
sed '/^$/d' test1.txt ----删除空行
3.5.6 sed命令替换
格式
行范围 s/旧字符串/新字符串/替换标记
替换标记
数字:表明新字符串将替换第几处匹配的地方
g:表面新字符串将会替换所有匹配的地方
p:打印与替换命令匹配的行,与-n一起使用
w文件:将替换的结果写入文件中
sed命令的替换符
s:替换字符串
c:整行替换
y:字符替换,替换前后的字符串长度必须相同
[root@localhost sed]#sed -n 's/root/test/2p' /etc/passwd --指定每一行的第二个root,替换为了test
[root@localhost sed]#sed -n 's/root/test/gp' /etc/passwd --所有的root都替换为test
[root@localhost sed]#sed -n '/^root/ s/^/#/p' /etc/passwd --以root开头开始处理,把开头为空的替换为#,注释掉
字母字符进行大小写的替换
[root@localhost sed]#sed 's/[A-Z]/\l&/g' test1.txt ---将大写全部转换为小写,
l&(小写字母)是转换小写的一种特殊的符号,前面要加转义符“\”
[root@localhost sed]#sed 's/[a-z]/\u&/' test1.txt ---把首字母替换成大写,
u&是转换首字母大写的一种特殊的符号,前面要加转义符“\”
整行替换
[root@localhost sed]# sed '/ONE/c 22' test1.txt #包含ONE字符的所有行都替换为22
[root@localhost sed]# sed '/TWO/c TEST' test1.txt #包含TWO字符的所有行都替换为TEST
单字符的替换
使用y,是对单个字符进行替换,每个字符需要一一对应,不是整体替换。前后字符串长度需要一致,不然会报错
只要有匹配的单字符会全部替换
[root@localhost sed]# sed 'y/TH/12/' test1.txt #字符长度一样,12替换TH
3.5.7 sed命令的增加
a:在下一行添加内容
i:在上一行插入内容
r:在行后读入文件内容
[root@localhost sed]# sed '/three/a 123' test1.txt #行后
[root@localhost sed]# sed '/three/i 123' test1.txt #上一行
[root@test1 opt]# sed '/three/r test.sh' 123.txt #当前行的下一行
[root@shell 98]# sed '/root/a 123' passwd #在root行下面添加123
root:x:0:0:root:/root:/bin/bash
123
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
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
[root@localhost sed]# sed '$r test2.txt' test1.txt ---先读取test1内容,然后在test1的末行插入test2的所有内容
[root@localhost opt]# sed '$a 123' 123.txt #在123.txt的文件最后一行插入123
[root@localhost opt]# sed '$i 123' 123.txt #在123.txt的文件最后后面的行中插入 倒数第二行
[root@shell 98]# sed '$r 3.txt' 1.txt
123
123
435
234
54
574
54
54
54
asf
Afsd
[root@shell 98]# cat 1.txt
123
123
435
234
54
574
54
54
54
[root@shell 98]# cat 3.txt
asf
Afsd
3.5.7 sed命令中字符串和字符的位置交换
[root@localhost opt]# echo ky29ztt | sed -r 's/(ky29)(ztt)/\2\1/'
yhtky27
[root@localhost opt]# echo ky27yhtdxl | sed -r 's/(ky27)(yht)(dxl)/\3\2\1/'
dxlyhtky27
[root@localhost opt]# echo ky27yhtdxl | sed -r 's/(ky27)(yht)(dxl)/\2\1/'
yhtky27
[root@localhost opt]# echo ky27yhtdxl | sed -r 's/(ky27)(yht)(dxl)/\3\1/'
dxlky27
[root@localhost opt]# echo ky27yhtdxl | sed -r 's/(ky27)(yht)(dxl)/\3\2/'
dxlyht
[root@localhost sed]#echo 123abc|sed -r 's/(.)(.)(.)(.)(.)(.)/\6\5\4\3\2\1/' #前面的点表示字符位置,后面的数字表示对应的交换顺序
3.5.8 sed -f 指定命令来对第二个文件的行进行处理
[root@localhost opt]# cat 123.txt
/IPADDR=192.168.233.21/c IPADDR=10.10.10.10
[root@localhost opt]# cat 456.txt
IPADDR=192.168.233.21
[root@localhost opt]# sed -f 123.txt 456.txt
IPADDR=10.10.10.10
扩展例题
提取版本号
[root@localhost opt]# grep -E "[0-9]+." 1.txt
ant-1.9.7.jar
ant-launcher-1.9.7.jar
antlr-2.7.7.jar
antlr-runtime-3.4.jar
aopalliance-1.0.jar
archaius-core-0.7.6.jar
asm-5.0.4.jar
aspectjweaver-1.9.5.jar
bcpkix-jdk15on-1.64.jar
bcprov-jdk15-1.46.jar
bcprov-jdk15on-1.64.jar
checker-compat-qual-2.5.5.jar
[root@localhost opt]# cat 1.txt |sed -r 's/(.)-(.)(.jar)/\1\2\3/' #完整版
[root@localhost opt]# cat 1.txt |sed -r 's/.-(.)(.jar)/\1\2/' #把-前面的取消了
[root@localhost opt]# cat 1.txt |sed -r 's/.-(.).jar/\1/' #把.jar是不在引用,正确结果
#-r 表示引用扩展正则,(.)表式"-"前面的所有,"-",就是"-",第二个(.)表示"-"后面的内容到.jar,(.jar)的第三个部分
1.9.7
1.9.7
2.7.7
3.4
1.0
0.7.6
5.0.4
1.9.5
1.64
1.46
1.64
2.5.5
查看指定时间内的日志
[root@localhost ~]#sed -n '/2023:08:09/,/2023:09:42:37/p' /var/log/messages #没有内容
[root@localhost network-scripts]# sed -n '/Mar 23 21:00:01/,/Mar 23 21:30:01/p' /var/log/messages #开头的格式要一致
Mar 23 21:00:01 localhost systemd: Started Session 70 of user root.
修改网卡的IP地址
[root@localhost network-scripts]# sed -i '/IPADDR=192.168.233.21/c IPADDR=10.10.10.10' ifcfg-ens33
[root@localhost network-scripts]# cat ifcfg-ens33
TYPE=Ethernet
DEVICE=ens33
ONBOOT=yes
BOOTPROTO=static
IPADDR=10.10.10.10
NETMASK=255.255.255.0
GATEWAY=192.168.233.2
DNS1=192.168.233.2
[root@localhost network-scripts]# sed -i 'y/10.10.10.10/192.168.233.21/' ifcfg-ens33 #用单个字符串替换会报错
sed:-e 表达式 #1,字符 29:“y”命令的字符串长度不同
总结
1.sed命令是一种流编辑器读取文件会进行逐行读取加上指令操作,所以过大的文件一定要拆分后再交给sed处理
2.sed -r 搭配扩展正则表达式使用,使用{n} {n,} {n,m} 不需要加“\”
3.用 -i 时一定要先备份(尤其对重要文件的操作),或者时先实验好确定无误时,再使用 -i
4.sed 命令 的重点在于增删改查四个功能,可以运用在脚本中对重要文件配置的修改,添加等作用尤其有效