正则expression式的可变长度lookbehind-assertion选项
在Python / PHP / JavaScript中是否有正则expression式的实现支持可变长度lookbehind-assertion?
/(?<!foo.*)bar/
我怎样才能写一个具有相同含义的正则expression式,但不使用lookbehind-assertion?
这种断言是否有可能在某一天实施?
我觉得事情好多了。
更新:
(1)已经有支持变长lookbehind-assertion的正则expression式实现。
Python模块的正则expression式 (不是标准的,但额外的regex
模块)支持这样的断言(并有许多其他很酷的function)。
>>> import regex >>> m = regex.search('(?<!foo.*)bar', 'f00bar') >>> print m.group() bar >>> m = regex.search('(?<!foo.*)bar', 'foobar') >>> print m None
对于我来说,有一些正则expression式是Perl无法做到的,而Python可以做到这一点,这真是一个非常大的惊喜。 也许,Perl的“增强的正则expression式”的实现呢?
(感谢和+1对MRAB)。
(2)现代正则expression式中有一个很酷的function\K
这个符号意味着当你进行replace时(从我的观点来看,最有趣的断言使用情况就是replace),在\K
之前find的所有字符都不能被改变。
s/unchanged-part\Kchanged-part/new-part/x
这几乎就像一个背后的断言,但当然不是那么灵活。
更多关于\K
:
- Perl Regular Expression \ K Trick
- PCRE Regex Spotlight:\ K
据我所知,你不能在同一个正则expression式中使用\ K两次。 而且你不能说出你想要“杀死”你find的angular色的点。 这总是一直到行的开始。
(感谢和ikegami + 1)。
我的其他问题:
- 是否有可能说出什么点必须是最终的效果?
- 那么为Perl / Ruby / JavaScript / PHP增强正则expression式实现呢? 就像Python的
regex
。
大多数情况下,通过使用\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
对于Python,有一个正则expression式的实现支持可变长度的lookbehinds:
http://pypi.python.org/pypi/regex
它被devise成与标准的重新模块向后兼容。
您可以反转string与模式,并使用可变长度的前瞻
(rab(?!\w*oof)\w*)
粗体匹配:
raboof rab7790oof raboo rabof rab rabo raboooof rabo
据我所知原始解决scheme:
Jeff'japhy'Pinyan
你显示的正则expression式会发现没有前面有foo
的bar
任何实例。
一个简单的select是首先将foo
与string进行匹配,并find第一个匹配的索引。 然后searchbar
,并查看是否可以find该索引之前的事件。
如果你想find不是直接在foo
前面的bar
实例,我也可以为它提供一个正则expression式(不使用lookbehind),但是它会非常难看。 基本上,反转/foo/
– /[^f]oo|[^o]o|[^o]|$/
。
foo.*|(bar)
如果foo
先在string中,那么正则expression式将匹配,但是不会有组。
否则,它会findbar
并将其分配给一个组。
所以你可以使用这个正则expression式,并在find的组中find你的结果:
>>> 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)) >>>
资源。