Cor*_*ong 7 regex negative-lookahead
伙计们,我正在尝试使用正则表达式处理大量的数字字符串,并匹配特定模式的数字序列,其中某些数字在组中重复.部分要求是确保给定模式的各部分之间的唯一性.
我想要实现的那种匹配的一个例子
ABBBCCDD
Run Code Online (Sandbox Code Playgroud)
将其解释为一组数字.但A,B,C,D不能相同.每个重复都是我们想要匹配的模式.
我一直在使用带有负面预测的正则表达式作为这种匹配的一部分,它可以工作,但不是所有的时间,我很困惑为什么.我希望有人可以解释为什么会出现故障并提出解决方案.
因此,为了解决ABBBCCDD,我使用负面预测使用组来提出这个RE.
(.)(?!\1{1,7})(.)\2{2}(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1}
Run Code Online (Sandbox Code Playgroud)
打破这个..
(.) single character wildcard group 1 (A)
(?!\1{1,7}) negative look-ahead for 1-7 occurrences of group 1 (A)
(.) single character wildcard group 2 (B)
\2{2} A further two occurrences of group 2 (B)
(?!\2{1,4}) Negative look-ahead of 1-4 occurrences of group 2 (B)
(.) single character wildcard group 3 (C)
\3{1} One more occurrence of group 3 (C)
(?!\3{1,2}) Negative look-ahead of 1-2 occurrences of group 3 (C)
(.) single character wildcard group 4 (D)
\4{1} one more occurrence of group 4 (D)
Run Code Online (Sandbox Code Playgroud)
这里的想法是,负面的前瞻作为一种手段来验证某个特定角色是否在意外的地方找不到.所以在接下来的7个字符中检查A. 一旦B和它的2次重复匹配,我们就会在接下来的4个字符中向前看待B.最后,一旦这对Cs匹配,我们将在最后的2中查找C作为检测不匹配的方法.
对于测试数据,此字符串"01110033"与表达式匹配.但它不应该因为A的'0'在C位置重复.
我在Python中运行了这个表达式的检查,并在PCRE模式下运行了grep(-P).两者都匹配错误的模式.
我把表达式放在https://regex101.com/以及相同的测试字符串"01110033",它也匹配在那里.我没有足够的评分来发布我尝试过的测试数据的图像.所以这里有一些来自grep -P的命令行运行的文本抓取
所以我们在CC位置重复A的无效表达式通过..
$ echo "01110033" | grep -P '(.)(?!\1{1,7})(.)\2{2}(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1}'
01110033
$
Run Code Online (Sandbox Code Playgroud)
将DD更改为11,复制BBB,我们也发现尽管B有正向否定检查,但仍然可以通过.
$ echo "01110011" | grep -P '(.)(?!\1{1,7})(.)\2{2}(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1}'
01110011
$
Run Code Online (Sandbox Code Playgroud)
现在将DD更改为"00",将CC数字复制到低位并看到它不匹配..
$ echo "01110000" | grep -P '(.)(?!\1{1,7})(.)\2{2}(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1}'
$
Run Code Online (Sandbox Code Playgroud)
从表达式中删除CC"(?!\ 3 {1,2})"的前向 - 否定检查,我们重复D位置的C位使其通过.
$ echo "01110000" | grep -P '(.)(?!\1{1,7})(.)\2{2}(?!\2{1,4})(.)\3{1}(.)\4{1}'
01110000
$
Run Code Online (Sandbox Code Playgroud)
返回原始测试编号并将CC数字切换为与B中相同的"1"使用.它无法通过.
$ echo "01111133" | grep -P '(.)(?!\1{1,7})(.)\2{2}(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1}'
$
Run Code Online (Sandbox Code Playgroud)
要为BBB组播放,请将B数字设置为与A遇到的相同的0.也无法匹配..
$ echo "00002233" | grep -P '(.)(?!\1{1,7})(.)\2{2}(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1}'
$
Run Code Online (Sandbox Code Playgroud)
然后取出A的负面预测,我们可以匹配..
$ echo "00002233" | grep -P '(.)(.)\2{2}(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1}'
00002233
$
Run Code Online (Sandbox Code Playgroud)
因此,在我看来,前向否定检查是有效的,但它只适用于下一个相邻的集合,或者它的预期前瞻范围在某种形式下被缩短,可能是我们试图匹配的额外事物.
如果我在B之后在A处添加额外的前瞻并且它的重复已被处理,我们得到它以避免在重复使用A数字的CC部分上匹配.
$ echo "01110033" | grep -P '(.)(?!\1{1,7})(.)\2{2}(?!\1{1,4})(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1}'
$
Run Code Online (Sandbox Code Playgroud)
为了更进一步,在匹配CC集之后,我需要再次重复A和B的负向前瞻.这似乎是错的.
希望RE专家可以澄清我在这里做错了什么,或者根据我观察的内容确认负面预测是否确实受到限制
(.)(?!.{0,6}\1)(.)\2{2}(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1}
^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
将您的值更改为在字符串中的任何位置出现lookahead
时禁止匹配。请参阅演示。您也可以在正则表达式中类似地修改其他部分。\1
https://regex101.com/r/vV1wW6/31