11.7.3 sed配合正则表达式的企业案例
11.7.3 sed配合正则表达式的企业案例
前文讲解正则表达式大多使用的是grep和egrep命令,本节就来讲解下sed配合正则表达式的用法,让读者掌握正则表达式的综合运用技巧。
问题1:取出Linux中执行ifconfig eth0后对应的IP地址(只能输出IP地址)。
这道题的解答方法非常多,本节主要讲解sed的组合方法,更多方法参见下文。
方法1:利用正则加sed替换功能获取IP。
步骤1:示例网卡eth0信息如下,目标是只输出10.0.0.7这个IP地址。
[root@oldboyedu ~]# ifconfig eth0
eth0: flags=4163 mtu 1500
inet 10.0.0.7 netmask 255.255.255.0 broadcast 10.0.0.255
inet6 fe80::9fdb:66ba:dc7f:3fe5 prefixlen 64 scopeid 0x20
ether 00:0c:29:2a:ca:54 txqueuelen 1000 (Ethernet)
RX packets 2501 bytes 236841 (231.2 KiB)
步骤2:首先找到第2行,然后去掉目标10.0.0.7这个IP之前的内容,可使用sed的替换功能来实现。
正则表达式的匹配技巧:处理所需要的目标(获取的IP)前的字符串一般以“..”开头(^.*)来匹配,最后将目标IP前的结尾写上实际的字符串(这里的字符串必须要唯一,否则就会贪婪匹配到最后一个相同的字符串),匹配的正则和实际要处理的第二行其匹配关系如图11-3所示。
图11-3 正则表达式匹配目标前面的内容图示
[root@oldboyedu ~]# ifconfig eth0|sed -n '2s#^.*inet##gp'
#<==-n默认不输出,2s表示处理第2行,“#^.*inet #”表示匹配IP地址前的所有内容(这里的空格暂且忽略),“##gp”表示全局替换为空内容,并打印输出替换后的内容。
10.0.0.7 netmask 255.255.255.0 broadcast 10.0.0.255 #<==IP地址前的所有字符都已经替换完毕。
步骤3:在步骤2的基础上,再去掉目标10.0.0.7这个IP后的所有内容,这里也是使用sed的替换功能来实现。
正则表达式匹配技巧:匹配目标后的字符串一般紧接目标(获取的IP)之后,匹配的正则表达式开头应写上实际的字符串(这里的字符串必须要唯一,否则就会贪婪匹配到最后一个相同的字符串),再结尾则是以“...”结尾(.*$)来匹配。匹配的正则表达式与实际要处理的第二行的匹配关系如图11-4所示。
图11-4 正则匹配目标后面的内容图示
[root@oldboyedu ~]# ifconfig eth0|sed -n '2s#^.*inet##gp'|sed -n 's#netm.*$##gp'
#<==注意最后一个管道后面的才是这次匹配的命令,-n默认不输出,#netm.*$#匹配了IP后面的所有字符(紧接着IP后的两个空格先暂且忽略),“##”表示替换为空,然后输出剩下的内容(就只有IP地址了)。
10.0.0.7 #<==此时的IP地址,实际上结尾和开头都是有空格的,也可以匹配这些空格并删掉。
[root@oldboyedu ~]# ifconfig eth0|sed -n '2s#^.*inet ##gp'|sed -n 's# netm.*$##gp' #<==inet后面匹配一个空格,netm前面匹配两个空格。
10.0.0.7 #<==结果就是只有ip,没有空格了。
提示:这里有个疑问,那就是为什么要用“.*”,而不用其他的更细致匹配的正则表达式呢?工作中的操作都是极简主义,只要能解决问题使用的越简单越好。
方法2:-e多项编辑可以减少管道的使用。
[root@oldboy test]# ifconfig eth0|sed -ne '2s#^.*inet ##g' -ne '2s# netm.*$##gp'
10.0.0.7
方法3:利用正则的“()”小括号和“n”后向引用功能加上替换来实现。
语法如下:
sed -rn 's#(oldboy)(oldgirl)(boy)#123#gp' oldboy.txt
其中,“1”表示第一个括号的内容,即oldboy,“2”表示第二个括号的内容,即oldgirl,“3”表示第三个括号的内容,即boy,以此类推,就是利用这个命令全匹配解决问题,“-r”表示支持扩展的正则表达式。匹配关系如图11-5所示。
图11-5 正则表达式匹配要获取的目标IP图示
需要特别注意的是,将要获取的目标(这里是IP地址)用小括号里的内容进行匹配,这样输出时就可以用“1”输出了,具体命令如下:
[root@oldboyedu ~]# ifconfig eth0|sed -nr '2s#^.*inet (.*) netm.*$#1#gp'#<==-r支持小括号功能。
#<==“1”用于获取小括号的内容输出,为什么(.*)就匹配到了IP呢?这是因为它前面明确匹配到字符串了,后面的开头也给出了固定匹配的字符串,因此中间的“.*”就只能是匹配IP了,也就是说根据目标前后匹配的结果就能知道中间的内容了。
10.0.0.7
提示:这种获取IP地址的方式实际上还是很复杂的,实际工作中还有很多更好的方法,这里仅仅是带大家练习一下正则表达式的使用。
下面留给读者一道类似的题,供读者练习:请取出stat/etc/hosts文件中第四行中的文件权限对应的644三个数字。
有关sed命令的更多知识,请参考https://blog.oldboyedu.com/commands-sed/。





