【问题标题】:Odd behavior on negative look behind in pythonpython中负面观察的奇怪行为
【发布时间】:2015-09-17 13:03:01
【问题描述】:

我正在尝试使用正则表达式进行 re.split,该正则表达式利用了后视。我想拆分前面没有 \r 的换行符。更复杂的是,如果 \n 前面有某个子字符串,我也不想拆分它:XYZ。

我可以通过安装正则表达式模块来解决我的问题,该模块让我可以在后面进行可变宽度组。但是,我试图避免安装任何东西。

我的工作正则表达式看起来像:

regex.split("(?<!(?:\r|XYZ))\n", s)

还有一个示例字符串:

s = "DATA1\nDA\r\n \r\n \r\nTA2\nDA\r\nTA3\nDAXYZ\nTA4\nDATA5"

拆分时的样子:

['DATA1', 'DA\r\n \r\n \r\nTA2', 'DA\r\nTA3', 'DAXYZ\nTA4', 'DATA5']

没有 regex 模块的我最接近的非工作表达式:

re.split("(?<!(?:..\r|XYZ))\n", s)

但是这种分裂导致:

['DATA1', 'DA\r\n \r', ' \r', 'TA2', 'DA\r\nTA3', 'DAXYZ\nTA4', 'DATA5']

这我不明白。根据我对后面的理解,最后一个表达式应该有效。知道如何使用基本 re 模块来完成此任务吗?

【问题讨论】:

  • 真的,您不需要正则表达式模块,请参阅 anubhava 的解决方案。他的解释少了一句:当一个look-behind有一些替代方案时,它们都必须是等宽的。而且你也不能在那里使用反向引用。

标签: python regex lookbehind


【解决方案1】:

你可以使用:

>>> re.split(r"(?<!\r)(?<!XYZ)\n", s)
['DATA1', 'DA\r\n \r\n \r\nTA2', 'DA\r\nTA3', 'DAXYZ\nTA4', 'DATA5']

在这里,我们将您的后向断言分为两个断言:

(?<!\r)  # previous char is not \r
(?<!XYZ) # previous text is not XYZ

由于此错误,Python 正则表达式引擎不允许 (?&lt;!(?:\r|XYZ)) 在后视中

error: look-behind requires fixed-width pattern

【讨论】:

    【解决方案2】:

    你可以使用re.findall

    >>> s = "DATA1\nDA\r\n \r\n \r\nTA2\nDA\r\nTA3\nDAXYZ\nTA4\nDATA5"
    >>> re.findall(r'(?:(?:XYZ|\r)\n|.)+', s)
    ['DATA1', 'DA\r\n \r\n \r\nTA2', 'DA\r\nTA3', 'DAXYZ\nTA4', 'DATA5']
    

    说明:

    (?:(?:XYZ|\r)\n|.)+ 这将匹配XYZ\n 或\r\n 贪婪,如果有任何如果要匹配的字符不是两者中的一个,那么控制转移到. 的或部分将匹配任何字符,但不是换行符。 + 在非捕获组之后会重复整个模式一次或多次。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-02
      • 1970-01-01
      • 1970-01-01
      • 2020-12-19
      • 1970-01-01
      相关资源
      最近更新 更多