shell编程6-shell三剑客(上)-文本处理工具sed
shell编程6-shell三剑客之文本处理工具sed
一.shell三剑客
在Linux/UNIX系统中包含很多文本处理器或文本编辑器,其中grep,sed和awk是shell编程中经常用到的文本处理工具,配合正则表达式使用就非常强大,因此,被业内的人广泛的称之为"shell编程三剑客".
其中grep擅长查找功能,sed擅长取行和替换,awk擅长取列.
有关grep命令的内容笔者在上篇内容已经大致讲解,此处不过多概述,只做大致了解
# grep参数详解
grep --help:
匹配模式选择:
Regexp selection and interpretation:
-E, --extended-regexp 扩展正则
-G, --basic-regexp 基本正则
-P, --perl-regexp 调用perl的正则
-e, --regexp=PATTERN use PATTERN for matching
-f, --file=FILE obtain PATTERN from FILE
-i, --ignore-case 忽略大小写
-w, --word-regexp 匹配整个单词
二.sed介绍
1.sed工作流程
- 读取: sed从输入流 (文件、管道、标准输入) 中读取一行内容并存储到临时的缓冲区中(又称模式空间,pattern space)
- 执行:默认情况下,所有的sed命令都在模式空间中顺序地执行,除非指定了行的地址,否则sed命令将会在所有的行上依次执行
- 显示:发送修改后的内容到输出流。在发送数据后,模式空间将会被清空。在所有的文件内容都被处理完成之前,上述过程将重复执行,直至所有内容被处理完。
在所有的文件内容都被处理完成之前,上述过程将重复执行,直至所有内容被处理完。 注意:默认情况下所有的sed命令都是在模式空间内执行的,因此输入的文件并不会发生任何变化,除非是用重定向存储输出
2.sed使用方法
sed常见的语法格式有两种,一种叫命令行模式,另一种叫脚本模式.
2.1命令行格式
- 格式和参数
sed [option] 'sed的命令|地址定位' filename
说明:引用shell script中的变量应使用双引号,而非通常使用的单引号
option:
-e 进行多项编辑,即对输入行应用多条sed命令时使用
-n 取消默认的输出
-f 指定sed脚本的文件名
-r 使用扩展正则表达式
-i inplace,原地编辑(修改源文件)
- 常用命令和选项
p 打印行
d 删除行
[root@shell-note ~]# sed -n "1p" test.txt
1111111111
[root@shell-note ~]# sed -n "2p" test.txt
2222222222
[root@shell-note ~]# sed -n "2,4p" test.txt
2222222222
2022-09-20
helloprogram
[root@shell-note ~]# sed "1d" test.txt
[root@shell-note ~]# sed "1,5d" test.txt
# 这里d删除并没有对文件内容进行操作,如果要操作文件内容需要加上-i参数
[root@shell-note ~]# sed -i "1d" test.txt
i\ 在当前行之前插入文本。多行时除最后一行外,每行末尾需用" \ "续行 vim——>O
a\ 在当前行后添加一行或多行。多行时除最后一行外,每行末尾需用" \ "续行 vim——> o
c\ 用此符号后的新文本替换当前行中的文本。多行时除最后一行外,每行末尾需用" \ "续行 整行替换
[root@shell-note ~]# sed "a111" test.txt
# 如果当前行在第一行则每行都会在之后添加一行111
[root@shell-note ~]# cat -n test.txt
# -n显示行数
[root@shell-note ~]# sed "chello world" test.txt
# 替换全部行为hello world
[root@shell-note ~]# sed "5chello world" test.txt
# 替换第5行内容为hello world
[root@shell-note ~]# sed "1,5chello world" test.txt
# 将1到5行内容替换为一行hello world
[root@shell-note ~]# sed "1i\
aaa\
bbb\
111" test.txt
# 在第一行之前添加一行内容aaabbb111
[root@shell-note ~]# sed "/^AI/c888888" test.txt
r 从文件中读取输入行
w 将所选的行写入文件
[root@shell-note ~]# sed "2r /etc/hosts" test.txt
# 在test.txt文件第二行之后新起一行添加/etc/hosts文件中的内容
[root@shell-note ~]# sed "/hero/w test.txt" 1.txt
# 将1.txt中包含hero的行写入test.txt文件
# 注意:test.txt文件会先被覆盖再写入you are the hero
[root@shell-note ~]# sed -r "/([0-9]{1,3}\.){3}[0-9]{1,3}/w 1.txt" test.txt
# 将正则匹配到的内容写入到1.txt中,1.txt会被覆盖再写入
! 对所选行以外的所有行应用命令,放到行数之后
[root@shell-note ~]# sed -n '1!p' 1.txt
# 注意此处使用单引号
# 单引号无法引用变量
# 双引号可以引用变量
[root@shell-note ~]# sed -n '1,2!p' 1.txt
s 用一个字符串替换另一个
g 在行内进行全局替换
# 这个也是笔者经常使用的参数
[root@shell-note ~]# sed -n "s/tbase/Tbase/p" test.txt
# 只显示在屏幕上, 不对文件进行修改
[root@shell-note ~]# sed -i "s/tbase/Tbase/g" test.txt
# 不显示在屏幕上,对文件进行修改
[root@shell-note ~]# sed -n "3s/hero/Hero/p" 1.txt
# 只在第三行查找hero替换为Hero
[root@shell-note ~]# sed -n "3s@hero@Hero@p" 1.txt
# 注意:搜索替换中的分隔符可以自己指定
[root@shell-note ~]# sed -n "1,3s/^/#/p" 1.txt
# 注释文件1到3行内容
# 笔者一般在文件中是用可视化模式修改,当然,这个方法无需进到文件即可操作,极为方便
& 保存查找串以便在替换串中引用 \(\)
[root@shell-note ~]# sed -n "s/tbase/#&/p" test.txt
# 在匹配到tbase的行前添加#
[root@shell-note ~]# sed -n "s/^1/#&/p" test.txt
# 注释以1开头的行
[root@shell-note ~]# sed -n "1,6s/^[a-z]/#&/p" test.txt
# 注释1到6行以小写字母开头的行
= 打印行号
[root@shell-note ~]# sed -n "/e$/=" test.txt
# 打印以e结尾的行的行号
[root@shell-note ~]# sed -n '/e$/=;/e$/p' test.txt
# 打印以e结尾的行的行号同时打印以e结尾的行内容
综合应用
[root@shell-note ~]# sed -n '1,3s/\(^\)/#\1/p' test.txt
#1111111111
#2222222222
#2022-09-20
选项:-e -r -i
-e 多项编辑
-r 扩展正则
-i 修改原文件
[root@shell-note ~]# sed -ne '/hero/p' 1.txt -ne '/hero/='
you are the hero
3
[root@shell-note ~]# sed -e "5itest" -e "8ahello" test.txt
# 在test.txt文件第五行之前插入test,在第8行之后插入hello
过滤vsftpd.conf文件中注释行和空行
[root@shell-note ~]# grep -Ev "^#|^$" /etc/vsftpd/vsftpd.conf
[root@shell-note ~]# sed '/^#/d;/^$/d' /etc/vsftpd/vsftpd.conf
过滤出smb.conf文件生效行
[root@shell-note ~]# sed -e '/^#/d' -e '/^;/d' -e '/^$/d' -e '/^\t$/d' -e '/^\t#/d' /etc/samba/smb.conf
# 过滤# ; tab开头以及tab开头后接#的行
[root@shell-note ~]# sed -r '/^(#|$|;|\t#|\t$)/d' /etc/samba/smb.conf
-i 选项 直接修改原文件
[root@shell-note ~]# sed -i "s/tbase/Tbase/g" test.txt
注意:
-ni 不要一起使用
p参数不要在使用-i时使用
- 总结
sed 选项 'sed命令或者正则表达式或者地址定位’ 文件名
定址用于决定对哪些行进行编辑。地址的形式可以是数字、正则表达式、或二者的结合。如果没有指定地址,sed将处理输入文件的所有行。
x 指定x行号 sed -n '5p' 1.txt
x,y 指定x到y行号 sed -n '1,5p' 1.txt
/key/ 查询包含关键字的行 sed -n '/root/p' 1.txt
/key1/,/key2/ 匹配包含两个关键字之间的行 sed -n '/^adm/,/^mysql/p' 1.txt
/key/,x 从匹配关键字的行开始到文件第x行之间的行(包含关键字所在行)sed -n '/^lp/,7p'
x,/key/ 从第x行开始到与关键字的匹配行之间的行
x,y! 不包含x到y行
[root@shell-note ~]# sed -n '/t/p' test.txt
[root@shell-note ~]# sed -n '/base$/!p' test.txt
注意:sed使用的正则表达式是括在斜杠线"/"之间的模式。
- 其他命令讲解
y命令
该命令与UNIX/Linux中的tr命令类似,字符按照一对一的方式从左到右进行转换。
正则表达式元字符对y命令不起作用。与s命令的分隔符一样,斜线可以被替换成其它的字符。
[root@shell-note ~]# sed "1s/10/20/" 1.txt
192.168.200.254
10.1.20.1
you are the hero
[root@shell-note ~]# sed "1y/10/20/" 1.txt
292.268.200.254
10.1.20.1
you are the hero
q 退出
[root@shell-note ~]# sed "2q" 1.txt
192.168.100.254
10.1.20.1
[root@shell-note ~]# sed -n '/hero$/p;2q' 1.txt
[root@shell-note ~]# sed -n '/hero$/p;3q' 1.txt
you are the hero
2.2脚本格式
- 用法
sed -f scripts.sed file
建议使用 ./sed.sh file
脚本的第一行需写上
#!/bin/sed -f
- 注意事项
1) 脚本文件是一个sed的命令行清单。'commands'
2) 在每行的末尾不能有任何空格、制表符(tab)或其它文本。
3) 如果在一行中有多个命令,应该用分号分隔。
4) 不需要且不可用引号保护命令
5) #号开头的行为注释
- 例
[root@shell-note ~]# vim sed.sh
#!/bin/sed -f
3a\
111111111
s/test/Test/g
# 在第三行之后添加一行111111111,替换文件中所有test为Test
[root@shell-note ~]# chmod +x sed.sh
# 为脚本增加x(执行)权限
[root@shell-note ~]# ./sed.sh test.txt
...
[root@shell-note ~]# vim 1.sed
#!/bin/sed -f
2atest
2d
[root@shell-note ~]# sed -f 1.sed 1.txt
192.168.100.254
test
you are the hero
三.sed和正则综合运用
1.正则表达式必须以”/“前后规范间隔
[root@shell-note ~]# sed -n "/hero$/p" 1.txt
you are the hero
2.如果匹配的是扩展正则表达式,需要使用-r选来扩展sed
grep -E
sed -r
+ ? () {n,m} | \d
[root@shell-note ~]# grep "[[:digit:]]+" 1.txt
[root@shell-note ~]# grep -E "[[:digit:]]+" 1.txt
192.168.100.254
10.1.20.1
注意:
在正则表达式中如果出现特殊字符(^$.*/[]),需要以前导 "\" 号做转义
[root@shell-note ~]# sed -n '/^\$/p' test.txt
3.逗号分隔符
[root@shell-note ~]# sed '1,2d' 1.txt
you are the hero
[root@shell-note ~]# sed -n "/t/,/st/p" test.txt
welcome to test.
192.168.10.254
10.1.1.254
AI2test
tbase
123@qq.com
abc
123456
# 打印第一个匹配字符t行到第一个匹配字符串st行中的行,循环执行
# 因为之后还有包含t的行,所以结束第一次查找后又找了一次
4.组合方式
[root@shell-note ~]# sed -n '1,/2022/p' test.txt
1111111111
2222222222
2022-09-20
# 打印第一行到第一个匹配字符串"2022"的所有行
[root@shell-note ~]# sed -n '/AI/,+2p' test.txt
AI2test
S1mple
tbase
# 打印第一个匹配字符串AI的行以及之后两行
[root@shell-note ~]# sed -n "1~5p" test.txt
1111111111
192.168.10.254
123@qq.com
# 从第一行开始每五行打印五行中的最后一行
[root@shell-note ~]# sed -nr "/test|AI/p" test.txt
welcome to test.
AI2test
# 打印配置字符串"test"或"AI"的行
[root@shell-note ~]# sed "1~2d" 1.txt
10.1.20.1
# 删除奇数行
[root@shell-note ~]# sed "0~2d" 1.txt
192.168.100.254
you are the hero
# 删除偶数行
5.特殊情况
[root@shell-note ~]# sed -n '1p' test.txt
1111111111
# 打印第一行
[root@shell-note ~]# sed -n '$p' test.txt
123456
# 打印最后一行
6.其他
[root@shell-note ~]# sed 's/.//' 1.txt
92.168.100.254
0.1.20.1
ou are the hero
# 删除每一行中的第一个字符
[root@shell-note ~]# sed 's/.//2' 1.txt
12.168.100.254
1.1.20.1
yu are the hero
# 删除每一行中的第二个字符
[root@shell-note ~]# sed 's/.$//' 1.txt
192.168.100.25
10.1.20.
you are the her
# 删除每一行中的最后一个字符
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)