shell - 正则表达式、sed流式编辑器

正则表达式概述

概述

使用“一串符号”来描述有共同属性的数据

基本正则列表

扩展正则列表

准备素材

[root@localhost ~]# head -5 /etc/passwd > user
[root@localhost ~]# cat user
root:x:0:0:root:/root:/bin/bash
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

测试 ^ $

[root@localhost ~]# grep root user
root:x:0:0:root:/root:/bin/bash
[root@localhost ~]# grep ^root user
root:x:0:0:root:/root:/bin/bash
[root@localhost ~]# grep root$ user
[root@localhost ~]# grep bash$ user
root:x:0:0:root:/root:/bin/bash
[root@localhost ~]# vim user
[root@localhost ~]# grep ^$ user  #^$代表空行


[root@localhost ~]# cat user
root:x:0:0:root:/root:/bin/bash
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

 
5

[root@localhost ~]# grep -v ^$ user  # -v 取反的意思,查询除空行之外的,空格这些也代表字符
root:x:0:0:root:/root:/bin/bash
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
 
5

[ ] 集合

匹配集合内任意一个字符,至少有一个就匹配成功

[^ ] 对集合取反

grep "[root]" user            #找r、o、t任意一个字符 
grep "[rot]" user                #效果同上
grep "[^rot]" user            #显示r或o或t以外的内容
grep "[0123456789]" user        #找所有数字
grep "[0-9]" user                #效果同上
grep "[^0-9]" user            #显示数字以外内容
grep "[a-z]" user                #找所有小写字母
grep "[A-Z]" user                #找所有大写字母
grep "[a-Z]" user                #找所有字母
grep "[^0-9a-Z]" user            #找所有符号

练习:编写脚本,问用户要整数数字,如果用户没有按要求则给出提示

#!/bin/bash
read -p "请输入一个整数数字: " n
echo $n | grep "[^0-9]"
[$? -ne 0 ] && echo ok || echo "必须输入数字

. 匹配单个字符

* 匹配前一个字符任意次数,不可以单独使用

.* 连接起来代表通配符

[root@localhost ~]# grep "*" user
[root@localhost ~]# grep "ro*t" user
root:x:0:0:root:/root:/bin/bash
[root@localhost ~]# grep ".*" user
root:x:0:0:root:/root:/bin/bash
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

 
5

测试 \{n\} \{n,\} \{n,m\} \(\)

grep "ro\{1,2\}t" user        #找rt,中间的o可以有1~2个
grep "ro\{2,6\}t" user        #找rt,中间的o可以有2~6个
grep "ro\{1,\}t" user            #找rt,中间的o可以有1个以及1个以上
grep "ro\{3\}t" user             #找rt,中间的o必须只有有3个
grep "\(0:\)\{2\}" user        #找连续的2个0:  小括号的作用是将字符组合为一个整体

扩展正则

grep "ro\{1,\}t" user            #使用基本正则找o出现1次以及1次以上
egrep "ro{1,}t" user            #使用扩展正则,效果同上,比较精简
egrep "ro+t" user                #使用扩展正则,效果同上,最精简
grep "roo\{0,1\}t" user        #使用基本正则找第二个o出现0~1次
egrep "roo{0,1}t" user        #使用扩展正则,效果同上,比较精简
egrep "roo?t" user            #使用扩展正则,效果同上,最精简
egrep "(0:){2}" user            #找连续的2个0:  小括号的作用是将字符组合为一个整体
egrep "root|bin" user            #找有root或者bin的行
egrep  "the\b" abc.txt            #找单词the,右边不允许出现数字、字母、下划线
egrep  "\bthe\b" abc.txt        #the两边都不允许出现数字、字母、下划线
egrep  "\<the\>" abc.txt        #效果同上

思考:如何匹配大范围的数字?比如250-255

方法一:
[root@localhost ~]# grep "25[0-5]" shuzi.txt 
253 456 234 34 254
方法二:
[root@localhost ~]# egrep "250|251|252|253|254|255" shuzi.txt 
253 456 234 34 254

sed基本用法 (sed流式编辑器,逐行处理)

概述

可以对文档进行非交互式增删改查

格式

前置指令 |  sed  选项  条件  指令

sed  选项  条件  指令  文档

选项、指令、条件

选项 -n 屏蔽默认输出

选项 -r 支持扩展正则

选项 -i 修改源文件

指令   p 输出  d 删除  s 替换

条件   行号  正则表达式

行号案例

head -5 /etc/passwd  >   user        #准备素材
sed -n  'p'  user                    #输出所有行
sed -n  '1p'  user                #输出第1行
sed -n  '2p'  user                #输出第2行
sed -n  '3p'  user                #输出第3行
sed -n  '2,4p'  user                #输出2~4行
sed -n  '2p;4p'  user                #输出第2行与第4行
sed -n '3,+1p' user                #输出第3行以及后面1行
sed -n '1~2p' /etc/passwd            #输出奇数行
sed -n '2~2p' /etc/passwd            #输出偶数行

 使用正则为条件

使用正则当条件
sed -n '/^root/p' user            #输出以root开头的行  
sed -n '/root/p' user                #输出包含root的行
sed -nr '/^root|^bin/p' user        #输出以root开头的行或bin开头的行,|是扩展正则,需要r选项

特殊用法
sed -n '1!p' user                    #输出除了第1行的内容,!是取反
sed -n '$p'  user                    #输出最后一行
sed -n '='  user                    #输出行号,如果是$=就是最后一行的行号

sed命令的s替换基本功能(s/旧内容/新内容/选项)

[root@svr5 ~]# vim  shu.txt                #新建素材
2017 2011 2018
2017 2017 2024
2017 2017 2017
sed 's/2017/6666/' shu.txt            #把所有行的第1个2017替换成6666
sed 's/2017/6666/2' shu.txt        #把所有行的第2个2017替换成6666
sed '1s/2017/6666/' shu.txt        #把第1行的第1个2017替换成6666
sed '3s/2017/6666/3' shu.txt        #把第3行的第3个2017替换成6666
sed 's/2017/6666/g' shu.txt         #所有行的所有个2017都替换
sed '/2024/s/2017/6666/g' shu.txt    #找含有2024的行,将里面的所有2017替换成6666

思考:如果想把 /bin/bash 替换成 /sbin/sh 怎么操作?

 sed综合脚本应用

实现以下需求:

  • 找到使用bash作登录Shell的本地账户名
  • 列出这些账户的shadow密码记录
  • 按每行“账户名 --> 密码记录”保存到文件中

#!/bin/bash
u=$(sed  -n  '/bash$/s/:.*//p'  /etc/passwd)        #找到passwd文档中以bash结尾的行,然后将行中冒号以及冒号后面内容都删除,此处的p代表仅仅显示s替换成功的行,最后赋值给u
for i in $u                            #将那些用bash的账户名交给for循环
do
pass=$(grep  $i  /etc/shadow)        #用每个账户名去shadow中找对应信息
pass=${pass#*:}                    #掐头,从左往右删除到第1个冒号
pass=${pass%%:*}                    #去尾,从右往左删除到最后一个冒号,经过上述步骤,pass就是最终要的密码了
echo "$i --> $pass"                #按格式喊出,如果要存到文件中就用追加重定向
done

正则表达式补充

\w 匹配数字、字母、下划线

egrep "roo\w" user   #找roo后面必须是数字或字母或下划线的字符串

\s 匹配空格、tab键

egrep "roo\s" user   #找roo后面是1个空格或者tab键打出来的空格的字符串,如果没有
就不输出

\d 匹配数字,和[0-9]等效

egrep "(25[0-5]\.|2[0-4][0-9]\.|1?[0-9]?[0-9]\.){3}(25[0-5]|2[0-4][0-9]|1?[0-9]?[0-9])"   #匹配ip地址
grep -P "(25[0-5]\.|2[0-4]\d\.|1?\d?\d\.){3}(25[0-5]|2[0-4]\d|1?\d?\d)"   #匹配ip地址

练习

匹配IP地址

 sed补充

a行下追加 i行上添加 c替换整行

sed 'a 666' user    #所有行的下面追加666
sed '1a 666' user   #第1行的下面追加666
sed '/^bin/a 666' user   #在以bin开头的行的下面追加666
sed 'i 666' user  #所有行的上面添加666
sed '5i 666' user   #第5行的上面添加666
sed '$i 666' user  #最后1行的上面添加666
sed 'c 666' user   #所有行都替换成666
sed '1c 666' user  #替换第1行为666

( )保留功能测试,保留就是复制的意思

cat abc.txt                                #先准备素材
100   laowang
98   gangge
59   laoniu
sed -r 's/([0-9]+)(\s+)([a-z]+)/\3\2\1/' abc.txt    #使用替换功能更改文本列,此处小括号相当于保留(复制),\1相当于粘贴之前第1个小括号里的内容

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值