对于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
注意:此问题与this one相同,但语言发生了变化。
答案 0 :(得分:16)
(强大的自我引用捕获组)
^(?:a(?=a*(\1?+b)b*(\2?+c)))+\1\2$
这个解决方案也被命名为#34; Qtax技巧"因为它使用与Qtax "vertical" regex matching in an ASCII "image"相同的技术。
所讨论的问题归结为需要断言三个组匹配相同的长度。作为简化版,要匹配:
xyz
其中x
,y
和z
实际上只是一个子模式,其变量的长度n
与a
,b
和{{ {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".
,a
,b
中的一个,它们以循环方式匹配,并且"计数"分别由c
,(?:a…)+
和(\1?+b)
组提供。通过额外的锚定和捕获我们开始的内容,我们可以断言我们匹配(\2?+c)
(代表上面的每个组)xyz
,x
和y
为{{1}分别是{,z
和an
。
作为奖励,以及#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
基本上我们首先断言有一个^ n b ^ n然后我们断言b ^ n c ^ n会导致一个^ n b ^ n c ^ n。