正则表达式匹配两组重复数字,其中两个都不允许是相同的数字

问题描述:

Folks, 我试图使用正则表达式来处理一大组数字串,并匹配特定模式的数字序列,其中一些数字是重复分组。部分要求是确保给定模式各部分之间的唯一性。正则表达式匹配两组重复数字,其中两个都不允许是相同的数字

那种匹配我的一个例子我试图实现

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和它的两个重复匹配,我们就会在接下来的4个字符中预测B的未来。最后,一旦这对Cs匹配,我们正在寻找C的最后2作为检测不匹配的手段。

对于测试数据,该字符串“01110033”与表达式匹配。但它不应该是因为A的'0'在C位置重复。

我在Python中用grep和PCRE模式(-P)运行了这个表达式的检查。两者都匹配错误的模式。

我将https://regex101.com/中的表达式与相同的测试字符串“01110033”一起放入并且在那里匹配。我没有足够的评分来张贴这些图片或者我尝试过的测试数据。因此,这里有来自命令行一些文本抓斗运行使用grep -P

所以我们的无效表达的是一个重复在CC位置获得通过..

$ 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}' 
$ 

至于遇到A.也没有出场比赛了这一点,对BBB组中,设置在B位数字相同的0 ..

$ echo "00002233" | grep -P '(.)(?!\1{1,7})(.)\2{2}(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1}' 
$ 

然后拿出了负先行一,我们可以这样来匹配..

$ echo "00002233" | grep -P '(.)(.)\2{2}(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1}' 
00002233 
$ 

所以,在我看来,正向负的检查工作,但它仅与相邻的下一个作品集或预期先行范围剪短一些用于大概是由我们试图匹配的额外东西。

如果我B及其重复已经被处理后加上右额外的前瞻,我们得到它,以避免对CC部分重用一个数字匹配..

$ 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专家能阐明我在做什么错在这里或者确认是否负前瞻的确是基于什么我观察

(.)(?!.{0,6}\1)(.)\2{2}(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1} 

    ^^^^^^^^ 

有限的更改您的lookahead不允许比赛时\1出现在任何地方在字符串中。参见demo.You可以类似地修改其他部分以及你的正则表达式。

https://regex101.com/r/vV1wW6/31

+0

感谢您的。这将特别适用于我展示的示例。然而,一些更复杂的模式将在后面的序列中重复A,B,C,D。 但根据你的回答,我刚刚发现使用..(?!。{0,6} \ 1)也可以作为在接下来的7个字符中测试我的组的方法,方法是将其作为0-6通配符由我的团队角色。所以我现在就用这种方法运行。再次感谢您的快速响应。 –

注意:更新。

正如vks已经指出的那样,您的负面预测并不排除您的想法 - 例如,\1{1,7}只会排除A,AA,AAA,AAAA,AAAAA,AAAAAA和AAAAAAA。我想你想的向前看符号是.*\1.*\2.*\3

但这里的另一个想法:这很容易预过滤出具有不相邻的重复字符的任何行:

grep -P -v '(.)(?!\1).*\1' 

然后你对结果的正则表达式简单得多:.{1}.{3}.{2}.{2}

而事实上整个事情可以使用第一次作为一个负前瞻预约束相结合:

(?!.*(.)(?!\1).*\1).{1}.{3}.{2}.{2} 

或者,如果你需要像你一样最初捕获的数字:

(?!.*(.)(?!\1).*\1)(.){1}(.){3}(.){2}(.){2} 

但是请注意,这些数字现在是\ 2 \ 3 \ 4 \ 5,由于\ 1是先行。

+1

感谢您的澄清。有一套我需要匹配的超过50种图案,并且它们会随着图案遍布整个地方。在某些情况下,相同的字符将会重复进一步。所以我最终不得不修改vks的解决方案为(?!。{0,6} \ 1),它将测试0-6野生,然后是\ 1,替代我认为的\ 1 {1,7}应该为我做。然后其他表情就变成了同样的技巧 –

+0

不客气。就是这样 - 在完成任何一个正确的解决方案之前,_complete_问题空间的大纲就是你/我们需要的。如果它真的“遍布这些模式的地方”,那么就没有一个通用的解决方案 - 你必须做到零碎。 –

根据迄今为止的反馈,我给出了另一个不依赖于根据总长进行算术运算的答案,它将自我识别长度序列1中的4个唯一字符/数字组的任何序列, 3,2,2字符串中的任意位置:

/(?<=^|(.)(?!\1))(.)\2{0}(?!\2)(.)\3{2}(?!\2|\3)(.)\4{1}(?!\2|\3|\4)(.)\5{1}(?!\5)/gm 
^^^^^^^^^^^^^^^^ this is a look-behind that makes sure we're starting with a new character/digit 
       ^^^^^^^^ this is the size-1 group; yes the \2{0} is superfluous 
         ^^^^^^ this ensures the next group is unique 
           ^^^^^^^^ this is the size-3 group 
etc. 

让我知道这是否更接近您的解决方案。如果是这样,并且如果你所有的“模式”都包含你正在寻找的组大小的序列(比如1,3,2,2),我可以想出一些代码来为任何这样的代码生成相应的正则表达式输入“模式”。

只是一些细节在这里是什么最终解决样子对我。

所以从根本上(?!\ 1 {1,7})不是我原以为这会是,是整个事业我遇到的问题。真诚赞赏你们为我找到这个问题。

我已经展示的例子是从大约50个1中,我必须从一组模式中制定。

它结束了作为..

ABBBCCDD 
09(.)(?!.{0,6}\1)(.)\2{2}(?!.{0,3}\2)(.)\3{1}(?!.{0,1}\3)(.)\4{1} 

所以一旦\ 1(A)被捕获,我测试的前述A. 0-6 wildchars负先行然后我捕获\ 2(B),它的两个重复,然后给出0-3百搭B的负视向等等。

它保持焦点为反面向前看,以确保被捕的团体不会重复他们不应该在的地方。接下来的捕获和他们的复发模式将在确保匹配方面做其余的事情。

从最后一组的其他例子:

ABCCDDDD 
(.)(?!.{0,6}\1)(.)(?!.{0,5}\2)(.)\3{1}(?!.{0,3}\3)(.)\4{3} 

AABBCCDD 
(.)\1{1}(?!.{0,5}\1)(.)\2{1}(?!.{0,3}\2)(.)\3{1}(?!.{0,1}\3)(.)\4{1} 

ABCCDEDE 
09(.)(?!.{0,6}\1)(.)(?!.{0,5}\2)(.)\3{1}(?!.{0,3}\3)(.)(?!\4{1})(.)\4{1}\5{1}