[英]regex optional group is skipped
我正在尝试在所需组中捕获可选组。 到目前为止,这是我的正则表达式:
BEGIN
(?<body>
(?<A>.*?) # in my regex just .*?
(?<B>START.*?STOP)?
(?<C>.*?) # in my regex just .*?
)
END
和输入:
junk1 BEGIN junk2 START content STOP junk3 END junk4
我得到这个:
match: 'BEGIN junk2 START content STOP junk3 END' # ok
group 'body': ' junk2 START content STOP junk3 ' # ok
group 'A': '' # expected: ' junk2 '
group 'B': not found # expected: 'START content STOP'
group 'C': ' junk2 START content STOP junk3 ' # expected: ' junk3 '
A和C组仅供参考
为什么即使没有正确的数据,B组也不匹配,并且如果B组不是可选的,我也会得到预期的结果?
您必须对正则表达式引擎和回溯的工作原理有一些基本的了解。 在这种情况下,它是这样的:
组(?<A>.*?)
将在第一次尝试时匹配空字符串(这就是表达式的含义:如果需要,则为空字符串或更多)。
然后我们在BEGIN
之后进入B
组,因为这里没有START
,整个内部组将失败,并且可选组将被跳过。
C
组将匹配空字符串。 然后,我们尝试匹配不匹配的END
。 因此,正则表达式引擎将尝试回溯最后一个量词。 在这种情况下,组C
。 它将一直执行到找到匹配项为止(或在尝试之前使用量词,直到失败)。
因此,我们最终将C
组扩展到END
,然后整个表达式匹配。
如果除了可选组中的不允许使用START
/ STOP
之外,则可以做出一个简单的解决方案,您可以使用以下表达式:
BEGIN
(?<body>
(?<A>
(?: (?!START|STOP) . )*? # do not match START nor STOP
)
(?<B>START.*?STOP)?
(?<C>
(?: (?!START|STOP) . )*? # do not match START nor STOP
)
)
END
模式前面的构造优先于模式后面的构造,而惰性量词( *?
)优先考虑较短的匹配。 因此,最佳匹配将始终是不匹配任何A
组,并且由于START
无法在第一个位置匹配,因此将被跳过。 最后, C
组将吃掉其余的字符串,因为END
不是可选的。
使用此代替:
BEGIN
(?<body>
(?<A>.*?)
(?:
(?<B>START.*?STOP)
(?<C>.*?)
)?
)
END
它将迫使A
组吃得尽可能多,直到B
的第一个匹配(如果存在)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.