在python中消极看的奇怪行为

时间:2015-09-17 13:03:02

标签: python regex lookbehind

我正在尝试使用正在使用look-behinds的正则表达式来执行re.split。我想拆分前面没有\ r \ n的换行符。为了使事情复杂化,我也不想在\ 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']

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

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

但这种分裂导致:

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

这个我不明白。根据我对后面的了解,这最后一个表达应该有效。知道如何用base re模块实现这个目标吗?

2 个答案:

答案 0 :(得分:1)

您可以使用:

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

这里我们将你的lookbehind断言分解为两个断言:

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

由于此错误,Python正则表达式引擎不允许(?<!(?:\r|XYZ))处于后视状态

error: look-behind requires fixed-width pattern

答案 1 :(得分:1)

您可以使用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如果要匹配的字符不是两个中的那个,那么控件转移到或者是.可以匹配任何字符但不包含换行符。非捕获组后的+将重复整个模式一次或多次。