44

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

(?<=this\sis\san\s*?)example

这应该做的是找到“this is an”,然后是空格字符,最后匹配单词“example”。现在,它不起作用,我不明白为什么,在lookbehinds中使用'+'或'*'是不可能的吗?

我也尝试了这两个,它们工作正常,但不能满足我的需求:

(?<=this\sis\san\s)example
this\sis\san\s*?example

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

4

5 回答 5

42

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

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

这些限制的原因主要是因为那些库根本不能向后处理正则表达式,或者只能处理有限的子集。

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

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

于 2012-01-27T09:52:19.950 回答
17

嘿,如果您不使用 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>'

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

于 2012-07-27T05:25:31.293 回答
5

Amber 说的是真的,但你可以用另一种方法解决它:非捕获括号组

(?<=this\sis\san)(?:\s*)example

这使它成为一个固定长度的外观,所以它应该可以工作。

于 2012-01-27T08:04:30.027 回答
0

大多数正则表达式引擎不支持后向断言的可变长度表达式。

于 2012-01-27T07:51:26.217 回答
0

您可以使用子表达式。

(this\sis\san\s*?)(example)

因此,要检索第 2 组“示例”,$2用于正则表达式,或者\2如果您使用的是格式字符串(例如 python's re.sub

于 2013-10-21T19:02:44.253 回答