php-正则表达式的变长lookbehind-assertion替代方法

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

/(?<!foo.*)bar/

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

是否有可能在一天之内实现这种断言?

我认为情况要好得多。

更新:

(1)已经有一些正则表达式实现支持变长后向断言。

Python模块正则表达式(不是标准re,而是其他regex模块)支持此类断言(并具有许多其他出色功能)。

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

对于我来说,令Perl和Python不能使用的正则表达式感到非常惊讶。 也许,Perl也有“增强的正则表达式”实现吗?

(感谢MRAB +1)。

(2)现代正则表达式中有一个很酷的功能regex

这个符号意味着当您进行替换时(从我的角度来看,断言最有趣的用例是替换),在regex之前找到的所有字符都不得更改。

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

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

有关regex的更多信息:

  • Perl正则表达式\ K技巧
  • PCRE Regex焦点:\ K

据我了解,您不能在同一正则表达式中两次使用\ K。 而且,直到说到要“杀死”您发现的角色,您都无法说出。 那总是一直到行的开始。

(感谢ikegami +1)。

我的其他问题:

  • 是否可以说regex效应的终点必须是哪一点?
  • Perl / Ruby / JavaScript / PHP的增强型正则表达式实现如何? 类似Python的regex
Igor Chubin asked 2020-08-11T12:12:52Z
5个解决方案
41 votes

在大多数情况下,您可以使用\K避免变长的回避。

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

将是

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

负向后看有点棘手。

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

将是

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

因为\KSTRING,因为[^CHAR]*CHAR


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

/foo.*bar/s

/^(?:(?!foo).)*bar/s
ikegami answered 2020-08-11T12:13:21Z
10 votes

对于Python,有一个regex实现,它支持可变长度的lookbehinds:

[HTTP://皮衣皮.Python.org/皮衣皮/热个性]

它被设计为与标准re模块向后兼容。

MRAB answered 2020-08-11T12:13:50Z
4 votes

您可以反转字符串和模式,并使用可变长度预读

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

粗体匹配:

raboof rab7790oof raboo rabof rabo raboooof rabo

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

杰夫(JP)

Benjamin Udink ten Cate answered 2020-08-11T12:14:28Z
2 votes

您显示的regexp将找到bar之前没有的任何实例foo

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

如果要查找bar的实例,而不是直接在foo之前的实例,我也可以为此提供一个正则表达式(不使用lookbehind),但是这样做非常丑陋。 基本上反转/foo/的意义-即/[^f]oo|[^o]o|[^o]|$/

Alex D answered 2020-08-11T12:15:24Z
2 votes
foo.*|(bar)

如果首先在字符串中包含bar,则正则表达式将匹配,但是将没有组。

否则,它将找到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))
>>> 

资源。

twasbrillig answered 2020-08-11T12:15:58Z
translate from https://stackoverflow.com:/questions/11640447/variable-length-lookbehind-assertion-alternatives-for-regular-expressions