正则表达式Lookbehind不适用于量词('+'或'*')

Noe*_*tin 27 regex lookbehind

我试图在正则表达式中使用lookbehinds,它似乎不像我预期的那样工作.所以,这不是我的真实用法,但为了简化,我将举一个例子.想象一下,我想在"这是一个例子"的字符串上匹配"example".所以,根据我对外观的理解,这应该有效:

(?<=this\sis\san\s*?)example
Run Code Online (Sandbox Code Playgroud)

这应该做的是找到"这是一个",然后是空格字符,最后匹配单词"example".现在,它不起作用,我不明白为什么,在外观中使用'+'或'*'是不可能的?

我也试过这两个,他们工作正常,但不满足我的需求:

(?<=this\sis\san\s)example
this\sis\san\s*?example
Run Code Online (Sandbox Code Playgroud)

我正在使用此站点来测试我的正则表达式:http://gskinner.com/RegExr/

Gum*_*mbo 29

许多正则表达式库只允许在后面的断言中使用严格表达式,例如:

  • 只匹配相同固定长度的字符串:( (?<=foo|bar|\s,\s)每个三个字符)
  • 只匹配固定长度的字符串:( (?<=foobar|\r\n)每个分支具有固定长度)
  • 只匹配上限长度的字符串:( (?<=\s{,4})最多四次重复)

造成这些限制的原因主要是因为这些库根本无法向后处理正则表达式,或者只能处理有限的子集.

另一个原因可能是避免作者构建过于复杂的正则表达式,因为它们具有所谓的病态行为(参见ReDoS).

另请参阅有关Regular-Expressions.info上的后断言限制的部分.

  • 在[我对这个问题的回答](/sf/ask/1210066721/#48727748)中,我列出了一些策略/在我遇到负向后查找的限制后的解决方法。希望它也能帮助其他人! (2认同)

Leo*_*eon 12

嘿,如果你没有使用python变量看看断言后面你可以通过转义匹配并通过使用重新开始欺骗正则表达式引擎\K.

这个网站解释得很好.. http://www.phpfreaks.com/blog/pcre-regex-spotlight-k ..

但是,当你有一个你匹配的表达式并且想要使用\ K得到它后面的所有内容时,它会强制它重新开始...

例:

string = '<a this is a tag> with some information <div this is another tag > LOOK FOR ME </div>'
Run Code Online (Sandbox Code Playgroud)

匹配/(\<a).+?(\<div).+?(\>)\K.+?(?=\<div)/ 将导致正则表达式在匹配结束div标记后重新启动,因此正则表达式将不包括结果中的正则表达式.这(?=\div)将使引擎在结束div标签之前获得所有内容


Boh*_*ian 5

Amber所说的是正确的,但是您可以使用另一种方法来解决它:不捕获括号的组

(?<=this\sis\san)(?:\s*)example
Run Code Online (Sandbox Code Playgroud)

这样一来,它就可以向后看固定长度,因此应该可以工作。

  • @micha不,不一样。这是一个*不吸引*的团体。我的正则表达式仅匹配`example`(不包含前导空格),但是您的示例*包括*前导空格 (3认同)
  • micha,在这种情况下,我更担心匹配部分而不是性能。非捕获组平均为 0.02451781 毫秒,没有它的平均为 0.02370844 毫秒。我不认为这是一个显着的区别。 (2认同)
  • 此正则表达式将匹配任何前面的空格。例如`this is an [example]`。(方括号表示匹配项)。仅仅因为它在非捕获组中,并不意味着它不匹配。这只是意味着它不会被捕获在通常用普通括号捕获的组中。正确的方法是使用@Lon这样的`\ K` (2认同)
  • 这是行不通的。匹配中包含领先空格。只需将其复制并粘贴到 https://regex101.com/ 中即可。 (2认同)