Linux Note / 奇淫技巧

正则零宽断言的一个注意点

Einic Yeo · 3月17日 · 2019年

正则的零宽断言的一个冷门知识点

一般来说’(?<’用在左边,’(?’用在右边,但是也有人反着用(倒不如说可以反着用)
下面现象看例子

[root@guan temp]# cat -n txt
     1	123,asdasd,23sfsdf,
     2	123,1nd.
     3	,addfsdf,hjgfj
     4	1,23t.fdgdfg,dfdg
     5	a,5ggh
     6	.asf,

先来一个正常的版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!,匹配一个字符后面逗号的到结尾

[root@guan temp]# grep -Pon '.(?=,).+' txt  
1:3,asdasd,23sfsdf,
2:3,1nd.
3:f,hjgfj
4:1,23t.fdgdfg,dfdg
5:a,5ggh
6:f,

然后去掉前面的字符,对比下结果

[root@guan temp]# grep -Pon '(?=,).+' txt
1:,asdasd,23sfsdf,
2:,1nd.
3:,addfsdf,hjgfj
4:,23t.fdgdfg,dfdg
5:,5ggh
6:,

可以理解为前面有字符后去掉前面的,或者理解为前面0个字符从这个字符版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!开始,也就是’(?<=正则)’但是保留这个正则部分,不能理解成(?版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!=,).+可以转换为,.+
原因看下面版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!例子

[root@guan temp]# cat txt
     1  ,23sfsdf,
     2  1nd,
     3  ,addfsdf,hjgfj
     4  1,23t.fdgdfg,dfdg
     5  a,5ggh
     6  .asf,
[root@guan temp]# grep -Pon '(?=,).+' txt
1:,23sfsdf,
2:,
3:,addfsdf,hjgfj
4:,23t.fdgdfg,dfdg
5:,5ggh
6:,
[root@guan temp]# grep -Pon ',.+' txt
1:,23sfsdf,
3:,addfsdf,hjgfj
4:,23t.fdgdfg,dfdg
5:,5ggh

总之(?=)用版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!在左边比较鸡肋
说下(?!)用在左边

[root@guan temp]# cat -n txt
     1	123,asdasd,23sfsdf,
     2	123,1nd.
     3	,addfsdf,hjgfj
     4	1,23t.fdgdfg,dfdg
     5	aa,5ggh
     6	.as.f,
     7	1al,sd.
     8	,wewqe
[root@guan temp]# grep -Pon '.(?!,).+' txt
1:123,asdasd,23sfsdf,
2:123,1nd.
3:,addfsdf,hjgfj
4:,23t.fdgdfg,dfdg
5:aa,5ggh
6:.as.f,
7:1al,sd.
8:,wewqe
[root@guan temp]# grep -Pon '(?!,).+' txt
1:123,asdasd,23sfsdf,
2:123,1nd.
3:addfsdf,hjgfj
4:1,23t.fdgdfg,dfdg
5:aa,5ggh
6:.as.f,
7:1al,sd.
8:wewqe

正则默认贪婪的,所以一般这样匹配到的是很多(?!)一般用在开头(原因看最后总结),(?!正则)来表示匹配正则部分开头但不包括它或者任意开头
上面就是开头的逗号,可以理解为无论开头有没有逗号都去掉开头的逗号

下面同理(?<=)用在右边比较鸡肋

[root@guan temp]# cat -n txt
     1	123,asdasd,23sfsdf,
     2	123,1nd.
     3	,addfsdf,hjgfj
     4	1,23t.fdgdfg,dfdg
     5	aa,5ggh
     6	.as.f,
     7	1al,sd.
     8	,wewqe
[root@guan temp]# grep -Pon '.+(?<=,).' txt
1:123,asdasd,2
2:123,1
3:,addfsdf,h
4:1,23t.fdgdfg,d
5:aa,5
7:1al,s
8:,w
[root@guan temp]# grep -Pon '.+(?<=,)' txt
1:123,asdasd,23sfsdf,
2:123,
3:,addfsdf,
4:1,23t.fdgdfg,
5:aa,
6:.as.f,
7:1al,
8:,

同理(?<!)表示无论结尾有没有正则部分,都去掉这部分

[root@guan temp]# cat txt
123,asdasd,23sfsdf,
123,1nd.
,addfsdf,hjgfj
1,23t.fdgdfg,dfdg
aa,5ggh
.as.f,
1al,sd.
,wewqe
[root@guan temp]# grep -Pon '.+(?<!,).' txt
1:123,asdasd,23sfsdf,
2:123,1nd.
3:,addfsdf,hjgfj
4:1,23t.fdgdfg,dfdg
5:aa,5ggh
6:.as.f,
7:1al,sd.
8:,wewqe
[root@guan temp]# grep -Pon '.+(?<!,)' txt
1:123,asdasd,23sfsdf
2:123,1nd.
3:,addfsdf,hjgfj
4:1,23t.fdgdfg,dfdg
5:aa,5ggh
6:.as.f
7:1al,sd.
8:,wewqe

总结的话就是
(?=)和(?<=)用在相反的方向都很鸡肋
(?!)和(?<!)用在相反方向一般是最左边和最右边这样反着用来去掉最开始的或者结尾的匹配的内容

参考文献


https://www.cnblogs.com/f-ck-need-u/p/7684762.html

0 条回应