Linux Note / 奇淫技巧

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

Einic Yeo · 3月17日 · 2019年

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

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

版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!
[[email protected] temp]# cat -n txt
     1	123,asdasd,23sfsdf,
     2	123,1nd.
     3	,addfsdf,hjgfj
     4	1,23t.fdgdfg,dfdg
     5	a,5ggh
     6	.asf,

先来一个正常的,匹配一个字符后面逗号的到结尾

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

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

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

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

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

总之(?=)用在左边比较鸡肋
说下(?!)用在左边

版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!
[[email protected] 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
[[email protected] 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
[[email protected] 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

正则默认贪婪的,所以一般这样匹配到的是很多(?!)一般用在开头(原因看最后总结),(?!正则)来表示匹配正则部分开头但不包括它或者任意开头
上面就是开头的逗号,可以理解为无论开头有没有逗号都去掉开版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!头的逗号

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

[[email protected] 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
[[email protected] 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
[[email protected] temp]# grep -Pon '.+(?<=,)' txt
1:123,asdasd,23sfsdf,
2:123,
3:,addfsdf,
4:1,23t.fdgdfg,
5:aa,
6:.as.f,
7:1al,
8:,

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

[[email protected] temp]# cat txt
123,asdasd,23sfsdf,
123,1nd.
,addfsdf,hjgfj
1,23t.fdgdfg,dfdg
aa,5ggh
.as.f,
1al,sd.
,wewqe
[[email protected] 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
[[email protected] 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 条回应