Linux grep 只返回匹配到的所需部分内容,不返回整行

linux下的grep可以对文件进行过滤,并返回匹配到的行,但有时我们只需要匹配行中的部分内容,而不是整行,一般都是用awk等对匹配行进行二次切分等。本文介绍一种用grep正则匹配模式只返回所需部分的内容,包括一行数据里匹配到多个结果。

参数

-o, --only-matching       show only the part of a line matching PATTERN

-o参数只返回匹配PATTERN的部分

-P, --perl-regexp
              Interpret PATTERN as a Perl regular expression.  This is highly experimental and grep -P  may  warn  of unimplemented features.

-P参数使用perl样式的正则表达式。

注意:查看man文档,perl正则部分还处于实验阶段,所以... 用还是不用自己决定。

正则表达式 Pattern

零宽,表示并不算匹配结果,但参与匹配的过程。

(?<=) 零宽度正预测先行断言

它断言自身出现的位置的后面能匹配表达式exp

(?<=exp)零宽度正回顾后发断言

它断言自身出现的位置的前面能匹配表达式exp

(.+?)匹配内容

参考Perl正则规则,其中

  • 点(.)表示任意字符
  • + 表示最少1个字符,不允许空
  • * 表示任意数量字符,可以为空
  • ?表示尽量少的匹配,比如一行可能有多次命中,如果不加,会造成第一个先行断言和最后一个后行断言之间整体返回,后面有例子

样例

如下以获得IP地址为例

默认匹配返回整行

无论是-E还是-P 都是返回整个匹配的行

[root@rh6-1 log]# echo "121212<IpAddress>10.0.2.201</IpAddress>343456"|grep -E '<IpAddress>.+?</IpAddress>'
121212<IpAddress>10.0.2.201</IpAddress>343456
[root@rh6-1 log]# echo "121212<IpAddress>10.0.2.201</IpAddress>343456"|grep -P '<IpAddress>.+?</IpAddress>'
121212<IpAddress>10.0.2.201</IpAddress>343456

一行一个匹配结果

此处的匹配Pattern为

'(?<=<IpAddress>)(.+?)(?=</IpAddress>)

表示匹配位置前面有<IpAddress>,匹配位置右面有</IpAddress>, 返回的是匹配到的10.0.2.201的IP

[root@rh6-1 log]# echo "121212<IpAddress>10.0.2.201</IpAddress>343456"|grep -oP '(?<=<IpAddress>)(.+?)(?=</IpAddress>)'
10.0.2.201
[root@rh6-1 log]# 

一行多个匹配结果

可以看到,一行数据匹配到了2个位置,结果集也是2行。

[root@rh6-1 log]# echo "121212<IpAddress>10.0.2.201</IpAddress>342<IpAddress>10.0.2.202</IpAddress>3456"|grep -oP '(?<=<IpAddress>)(.+?)(?=</IpAddress>)'
10.0.2.201
10.0.2.202

其中的匹配位置包括了? 最短匹配,如果没有,返回结果如下

[root@rh6-1 log]# echo "121212<IpAddress>10.0.2.201</IpAddress>342<IpAddress>10.0.2.202</IpAddress>3456"|grep -oP '(?<=<IpAddress>)(.+)(?=</IpAddress>)'
10.0.2.201</IpAddress>342<IpAddress>10.0.2.202

这个包含了2个IP以及之间其它字符的结果,肯定不是预期的结果。

参考

https://www.cnblogs.com/gelare/p/12651418.html