正则表达式的可变长度lookbehind-assertion替代方案

时间:2012-07-24 22:52:35

标签: php javascript python regex perl

Python / PHP / JavaScript中是否有正则表达式的实现支持可变长度的lookbehind-assertion?

/(?<!foo.*)bar/

如何编写具有相同含义但不使用lookbehind-assertion的正则表达式?

这种断言是否有可能在某一天实施?

我认为事情要好得多。

更新

(1)有正则表达式实现已经支持可变长度的lookbehind-assertion。

Python模块regex(非标准re,但附加regex模块)支持此类断言(并且还有许多其他很酷的功能)。

>>> import regex
>>> m = regex.search('(?<!foo.*)bar', 'f00bar')
>>> print m.group()
bar
>>> m = regex.search('(?<!foo.*)bar', 'foobar')
>>> print m
None

对我而言,Perl无法做到的正则表达式中有一些东西可以让我感到非常惊讶。可能还有Perl的“增强正则表达式”实现吗?

(谢谢和MRAB +1)。

(2)现代正则表达式中有一个很酷的特征\K

这个符号意味着当你进行替换时(从我的观点来看,断言最有趣的用例是替换),所有在\K之前找到的字符都不能被改变。

s/unchanged-part\Kchanged-part/new-part/x

这几乎就像一个后视断言,但当然不那么灵活。

有关\K的更多信息:

据我了解,你不能在同一个正则表达式中使用\ K两次。而且你不能说你想要“杀死”你找到的角色。这一直是直到行的开始。

(谢谢和池上+1)。

我的其他问题:

  • 是否可以说\K效果的最后一点必须是什么点?
  • Perl / Ruby / JavaScript / PHP的增强正则表达式实现怎么样?类似于regex的Python。

5 个答案:

答案 0 :(得分:40)

大多数情况下,您可以使用\K来避免可变长度的外观。

s/(?<=foo.*)bar/moo/s;

将是

s/foo.*\Kbar/moo/s;

负面的外观有点棘手。

s/(?<!foo.*)bar/moo/s;

将是

s/^(?:(?!foo).)*\Kbar/moo/s;

因为(?:(?!STRING).)*STRING[^CHAR]*CHAR


如果您只是匹配,则可能甚至不需要\K

/foo.*bar/s

/^(?:(?!foo).)*bar/s

答案 1 :(得分:10)

对于Python,有一个正则表达式实现,它支持可变长度的lookbehinds:

http://pypi.python.org/pypi/regex

它旨在向后兼容标准re模块。

答案 2 :(得分:4)

您可以反转字符串AND模式并使用可变长度前瞻

(rab(?!\w*oof)\w*)

以粗体显示:

  

raboof rab7790oof raboo rabof rab rabo raboooof rabo

根据我所知的原始解决方案:

  

Jeff'japhy'Pinyan

答案 3 :(得分:2)

您展示的正则表达式会在bar之前找到foo 之前的任何实例。

一个简单的替代方法是首先匹配字符串foo,并找到第一次出现的索引。然后搜索bar,看看是否可以在索引之前找到出现的事件。

如果你想找到bar之前不是直接foo实例,我还可以为它提供一个正则表达式(不使用lookbehind),但它会非常难看。基本上,颠倒/foo/的意义 - 即/[^f]oo|[^o]o|[^o]|$/

答案 4 :(得分:2)

foo.*|(bar)

如果foo首先在字符串中,那么正则表达式将匹配,但不会有任何组。

否则,它会找到bar并将其分配给一个组。

因此,您可以使用此正则表达式并在找到的组中查找结果:

>>> import re
>>> m = re.search('foo.*|(bar)', 'f00bar')
>>> if m: print(m.group(1))
bar
>>> m = re.search('foo.*|(bar)', 'foobar')
>>> if m: print(m.group(1))
None
>>> m = re.search('foo.*|(bar)', 'fobas')
>>> if m: print(m.group(1))
>>> 

Source.