匹配a ^ n b ^ n c ^ n用于n> PCRE为0

时间:2015-04-25 14:21:03

标签: regex pcre

对于n>,您将如何匹配^ n b ^ n c ^ n PCRE是0吗?

以下情况应符合:

abc
aabbcc
aaabbbccc

以下情况不符合:

abbc
aabbc
aabbbccc

这是我尝试过的事情&#34 ;; /^(a(?1)?b)$/gmx但是这匹配n ^的b ^ n> 0:

ab
aabb
aaabbb

Online demo

  

注意:此问题与this one相同,但语言发生了变化。

2 个答案:

答案 0 :(得分:16)

Qtax技巧

(强大的自我引用捕获组)

^(?:a(?=a*(\1?+b)b*(\2?+c)))+\1\2$

这个解决方案也被命名为#34; Qtax技巧"因为它使用与Qtax "vertical" regex matching in an ASCII "image"相同的技术。

所讨论的问题归结为需要断言三个组匹配相同的长度。作为简化版,要匹配:

xyz

其中xyz实际上只是一个子模式,其变量的长度nab和{{ {1}}。对于使用具有自引用捕获组的前瞻的表达式,我们指定的字符将添加到前瞻的每个重复中,这可以有效地用于" count":

aaabbbccc
 ^  ^  ^

这可以通过以下方式实现:

  • c子模式(?:a…)+的字符匹配。使用a,我们会直接跳到"计数器"。
  • (?=a*捕获群组((\1?+b))有效地消耗之前已匹配的内容(如果有),并使用不允许回溯的占有匹配,以及如果计数器不同步,则匹配失败 - 也就是说,子模式\1比子模式b更多。在第一次迭代中,这是不存在的,并且没有任何匹配。然后,子模式a的字符匹配。 它被添加到捕获组中,有效地"计数"该组b中的一个。 b,我们会直接跳到下一个"计数器&#34}。
  • b*捕获群组((\2?+c))有效地消耗了之前匹配的内容,如上所述。由于此附加字符捕获的工作方式与上一个组相同,因此允许字符在这些字符组中进行长度同步。假设\2的连续序列:

(请原谅我的艺术。)

第一次迭代:

a..b..c..

第二次迭代:

| The first 'a' is matched by the 'a' in '^(?:a…)'.
| The pointer is stuck after it as we begin the lookahead.
v,- Matcher pointer
aaaa...bbbbbbbb...cccc...
 ^^^   |^^^       ^
skipped| skipped  Matched by c in (\2?+c);
by a*  | by b*         \2 was "nothing",
       |               now it is "c".
       Matched by b
       in (\1?+b).
     \1 was "nothing", now it is "b".

正如上面讨论的三个小组"消费"分别是 | The second 'a' is matched by the 'a' in '^(?:a…)'. | The pointer is stuck after it as we begin the lookahead. v,- Matcher pointer aaaa...bbbbbbbb...cccc... /|^^^ |^ eaten by| skipped |Matched by c in (\2?+c); \1?+ | by b* | '\2' was "nothing", ^^ | \2?+ now it is "cc". skipped| by a* \ Matched by b in (\1?+b). '\1' was "nothing", now it is "bb". ab中的一个,它们以循环方式匹配,并且"计数"分别由c(?:a…)+(\1?+b)组提供。通过额外的锚定和捕获我们开始的内容,我们可以断言我们匹配(\2?+c)(代表上面的每个组)xyzxy为{{1}分别是{,zan

作为奖励,以及#34;计数"更多,人们可以这样做:

Pattern: ^(?:a(?=a*(\1?+b)b*(\2?+c)))+\1{3}\2$
Matches: abbbc
aabbbbbbcc
aaabbbbbbbbbccc
Pattern: ^(?:a(?=a*(\1?+bbb)b*(\2?+c)))+\1\2$
Matches: abbbc
aabbbbbbcc
aaabbbbbbbbbccc

答案 1 :(得分:11)

首先,让我们解释一下你所拥有的模式:

if 'stringC' in my_cell_array

使用以下修饰符:

^               # Assert begin of line
    (           # Capturing group 1
        a       # Match a
        (?1)?   # Recurse group 1 optionally
        b       # Match b
    )           # End of group 1
$               # Assert end of line

递归部分是可选的,以便最终退出“无限”递归。

我们可以使用上述模式来解决问题。我们需要添加一些正则表达式来匹配g: global, match all m: multiline, match start and end of line with ^ and $ respectively x: extended, indentation are ignored with the ability to add comments with # 部分。问题是在c中匹配aabb时,它已经消耗,这意味着我们无法追溯。

解决方案?使用前瞻!前瞻是零宽度,这意味着它不会消耗并向前移动。看看:

aabbcc

Online demo

基本上我们首先断言有一个^ n b ^ n然后我们断言b ^ n c ^ n会导致一个^ n b ^ n c ^ n。