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
# 删除每一行中的最后一个字符
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值