如何将n> 0的^ nb ^ nc ^ n与PCRE匹配?
以下情况应符合:
abc
aabbcc
aaabbbccc
Run Code Online (Sandbox Code Playgroud)
以下情况不符合:
abbc
aabbc
aabbbccc
Run Code Online (Sandbox Code Playgroud)
这是我"尝试过"的东西; /^(a(?1)?b)$/gmx但这匹配n> 0的^ nb ^ n:
ab
aabb
aaabbb
Run Code Online (Sandbox Code Playgroud)
注意:这个问题是一样的这一个与语言的变化.
Uni*_*ron 16
(强大的自我引用捕获组)
^(?:a(?=a*(\1?+b)b*(\2?+c)))+\1\2$
Run Code Online (Sandbox Code Playgroud)
这个解决方案也被称为"Qtax技巧",因为它使用与Qtax 的ASCII"图像"中"垂直"正则表达式匹配相同的技术.
所讨论的问题归结为需要断言三个组具有相同长度的匹配.作为简化版,要匹配:
xyz
Run Code Online (Sandbox Code Playgroud)
其中x,y并且z实际上只是具有匹配长度n为的变量的子模式a,b和c.对于使用具有自引用捕获组的前瞻的表达式,我们指定的字符将添加到前瞻的每个重复中,这可以有效地用于"计数":
aaabbbccc ^ ^ ^
这是通过以下方式实现的:
(?:a…)+子模式的字符a匹配.有了(?=a*,我们直接跳到"柜台".(\1?+b)捕获组(\1)有效地消耗任何先前已经匹配,如果它的存在,并使用所有格匹配它不允许回溯,如果计数器超出同步匹配失败-也就是说,出现了更多的子模式的b比子模式a.在第一次迭代中,这是不存在的,并且没有任何匹配.然后,b匹配子模式的字符.它被添加到捕获组中,有效地"计算" b组中的一个.有了b*,我们直接跳到下一个"柜台".(\2?+c)捕获group(\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".
Run Code Online (Sandbox Code Playgroud)
第二次迭代:
| 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".
Run Code Online (Sandbox Code Playgroud)
如上所讨论的三组"消耗"的每一个中的一个a,b,c分别,他们是在循环式匹配并且由"计数" (?:a…)+,(\1?+b)和(\2?+c)分别的基团.随着更多的锚定和捕捉我们开始,我们可以断言,我们匹配xyz(代表每一组以上),其中x,y和z是,和分别.anbncn
作为奖励,要"计算"更多,可以这样做:
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
Ham*_*mZa 11
首先,让我们解释一下你所拥有的模式:
^ # 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
Run Code Online (Sandbox Code Playgroud)
使用以下修饰符:
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 #
Run Code Online (Sandbox Code Playgroud)
递归部分是可选的,以便最终退出"无限"递归.
我们可以使用上面的模式来解决问题.我们需要添加一些正则表达式来匹配该c部分.问题是当aabb匹配时aabbcc,它已被消耗,这意味着我们无法追溯.
解决方案?使用前瞻!前瞻是零宽度,这意味着它不会消耗并向前移动.看看这个:
^ # Assert begin of line
(?= # First zero-with lookahead
( # Capturing group 1
a # Match a
(?1)? # Recurse group 1 optionally
b # Match b
) # End of group 1
c+ # Match c one or more times
) # End of the first lookahead
(?= # Second zero-with lookahead
a+ # Match a one or more times
( # Capturing group 2
b # Match b
(?2)? # Recurse group 2 optionally
c # Match c
) # End of group 2
) # End of the second lookahead
a+b+c+ # Match each of a,b and c one or more times
$ # Assert end of line
Run Code Online (Sandbox Code Playgroud)
基本上我们首先断言有一个^ nb ^ n,然后我们断言b ^ nc ^ n,这将导致^ nb ^ nc ^ n.
| 归档时间: |
|
| 查看次数: |
2806 次 |
| 最近记录: |