【发布时间】:2015-09-29 11:20:48
【问题描述】:
各位, 我正在尝试使用正则表达式来处理大量数字字符串并匹配特定模式的数字序列,其中某些数字在组中重复。部分要求是确保给定模式的各个部分之间的唯一性。
我正在尝试实现的匹配示例
ABBBCCDD
将其解释为一组数字。但是 A,B,C,D 不能相同。每个的重复是我们试图匹配的模式。
我一直在使用带有负前瞻的正则表达式作为此匹配的一部分,它有效,但并非一直有效,我不知道为什么。我希望有人能解释为什么它会出现故障并提出解决方案。
因此,为了解决 ABBBCCDD,我提出了这个 RE,使用了使用组的负前瞻..
(.)(?!\1{1,7})(.)\2{2}(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1}
分解这个..
(.) 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)
这里的想法是,负前瞻是一种验证给定字符是否未在意外位置找到的方法。所以 A 在接下来的 7 个字符中得到检查。一旦 B 和它的 2 次重复匹配,我们就会在接下来的 4 个字符中消极地寻找 B。最后,一旦这对 C 匹配,我们就会在最后的 2 个中寻找一个 C 作为检测不匹配的方法。
对于测试数据,此字符串“01110033”与表达式匹配。但这不应该是因为 A 的“0”在 C 位置重复。
我在 Python 中检查了这个表达式,并在 PCRE 模式下使用 grep (-P)。两者都匹配了错误的模式。
我将表达式与相同的测试字符串“01110033”一起放入https://regex101.com/,它也在那里匹配。我没有足够的评级来发布这个或我用测试数据尝试过的变体的图像。所以这里有一些使用 grep -P 命令行运行的文本抓取
所以我们在 CC 位置重复 A 的无效表达式通过了..
$ echo "01110033" | grep -P '(.)(?!\1{1,7})(.)\2{2}(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1}'
01110033
$
将 DD 更改为 11,复制 BBB,我们也发现尽管 B 有一个正向否定检查,但仍然可以通过..
$ echo "01110011" | grep -P '(.)(?!\1{1,7})(.)\2{2}(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1}'
01110011
$
现在将 DD 更改为“00”,复制 CC 数字和低位,结果不匹配..
$ echo "01110000" | grep -P '(.)(?!\1{1,7})(.)\2{2}(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1}'
$
从表达式中删除对 CC "(?!\3{1,2})" 的正负检查,我们在 D 位置重复 C 数字使其通过。
$ echo "01110000" | grep -P '(.)(?!\1{1,7})(.)\2{2}(?!\2{1,4})(.)\3{1}(.)\4{1}'
01110000
$
回到原来的测试号,把CC数字换成和B一样用的“1”,打不通。
$ echo "01111133" | grep -P '(.)(?!\1{1,7})(.)\2{2}(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1}'
$
要为 BBB 组执行此操作,请将 B 数字设置为与 A 遇到的相同的 0。也无法匹配..
$ echo "00002233" | grep -P '(.)(?!\1{1,7})(.)\2{2}(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1}'
$
然后取出 A 的负前瞻,我们可以匹配..
$ echo "00002233" | grep -P '(.)(.)\2{2}(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1}'
00002233
$
所以在我看来,前向否定检查是有效的,但它只适用于下一个相邻的集合,或者它的预期超前范围以某种形式被缩短,大概是由于我们试图匹配的额外事物。
如果我在 B 之后立即在 A 上添加一个额外的前瞻,并且它的重复已被处理,我们会得到它以避免在 CC 部分上重复使用 A 数字进行匹配..
$ echo "01110033" | grep -P '(.)(?!\1{1,7})(.)\2{2}(?!\1{1,4})(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1}'
$
为了更进一步,在匹配 CC 集之后,我需要再次对 A 和 B 重复负前瞻。这似乎是错误的。
希望 RE 专家可以澄清我在这里做错了什么,或者根据我所观察到的情况确认负前瞻是否确实受到限制
【问题讨论】: