我不知道可以捕获量词的正则表达式引擎。但是,PCRE 或 Perl 可以使用一些技巧来检查您是否有相同数量的字符。用你的例子:
@@@@ “星球大战” ==== “1977” ---- “科幻小说” //// “乔治卢卡斯”
您可以检查是否与使用
著名的 Qtax 技巧的@
=
-
/
这种模式保持平衡,(您准备好了吗?):
“拥有-可选的自引用组”
~(?<!@)((?:@(?=[^=]*(\2?+=)[^-]*(\3?+-)[^/]*(\4?+/)))+)(?!@)(?=[^=]*\2(?!=)[^-]*\3(?!-)[^/]*\4(?!/))~
图案细节:
~ # pattern delimiter
(?<!@) # negative lookbehind used as an @ boundary
( # first capturing group for the @
(?:
@ # one @
(?= # checks that each @ is followed by the same number
# of = - /
[^=]* # all that is not an =
(\2?+=) # The possessive optional self-referencing group:
# capture group 2: backreference to itself + one =
[^-]*(\3?+-) # the same for -
[^/]*(\4?+/) # the same for /
) # close the lookahead
)+ # close the non-capturing group and repeat
) # close the first capturing group
(?!@) # negative lookahead used as an @ boundary too.
# this checks the boundaries for all groups
(?=[^=]*\2(?!=)[^-]*\3(?!-)[^/]*\4(?!/))
~
主要思想
非捕获组仅包含一个@
. 每次重复该组时,都会在捕获组 2、3 和 4 中添加一个新角色。
所有格-可选自指组
它是如何工作的?
( (?: @ (?= [^=]* (\2?+ = ) .....) )+ )
在第一次出现 @ 字符时,捕获组 2 尚未定义,因此您不能编写类似的东西,(\2 =)
这会使模式失败。为了避免这个问题,方法是使反向引用可选:\2?
该组的第二个方面是=
匹配的字符数在每次重复非捕获组时递增,因为=
每次都添加 an。为了确保这个数字总是增加(或模式失败),所有格量词强制在添加新=
字符之前首先匹配反向引用。
请注意,该组可以这样看:如果组 2 存在,则将其与下一个匹配=
( (?(2)\2) = )
递归方式
~(?<!@)(?=(@(?>[^@=]+|(?-1))*=)(?!=))(?=(@(?>[^@-]+|(?-1))*-)(?!-))(?=(@(?>[^@/]+|(?-1))*/)(?!/))~
您需要使用重叠匹配,因为您将多次使用 @ 部分,这就是所有模式都在环顾内的原因。
图案细节:
(?<!@) # left @ boundary
(?= # open a lookahead (to allow overlapped matches)
( # open a capturing group
@
(?> # open an atomic group
[^@=]+ # all that is not an @ or an =, one or more times
| # OR
(?-1) # recursion: the last defined capturing group (the current here)
)* # repeat zero or more the atomic group
= #
) # close the capture group
(?!=) # checks the = boundary
) # close the lookahead
(?=(@(?>[^@-]+|(?-1))*-)(?!-)) # the same for -
(?=(@(?>[^@/]+|(?-1))*/)(?!/)) # the same for /
与先例模式的主要区别在于,这种模式不关心=
-
和/
组的顺序。(但是,您可以轻松地对第一个模式进行一些更改以处理该问题,使用字符类和负前瞻。)
注意:对于示例字符串,更具体地说,您可以用锚(^
或\A
)替换否定的lookbehind。如果你想获得整个字符串作为匹配结果,你必须.*
在最后添加(否则匹配结果将是空的,因为好玩会注意到它。)