python 中消极回头的奇怪行为
Odd behavior on negative look behind in python
我正在尝试 re.split 使用利用后视的正则表达式。我想拆分前面没有 \r 的换行符。使事情复杂化的是,如果它前面有某个子字符串,我也不想在 \n 上拆分:XYZ.
我可以通过安装 regex 模块来解决我的问题,该模块让我可以在后视中进行可变宽度分组。但是,我试图避免安装任何东西。
我的工作正则表达式看起来像:
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']
而这个我不明白。根据我对 look behinds 的理解,这最后一个表达式应该有效。知道如何使用基本 re 模块完成此操作吗?
您可以使用:
>>> 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 由于此错误
,正则表达式引擎将不允许 (?<!(?:\r|XYZ))
后视
error: look-behind requires fixed-width pattern
您可以使用 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
如果匹配的字符不是两者中的那个则控制转移到or 部分即 .
可以匹配任何字符但不匹配换行符。 +
之后非捕获组会重复整个模式一次或多次。
我正在尝试 re.split 使用利用后视的正则表达式。我想拆分前面没有 \r 的换行符。使事情复杂化的是,如果它前面有某个子字符串,我也不想在 \n 上拆分:XYZ.
我可以通过安装 regex 模块来解决我的问题,该模块让我可以在后视中进行可变宽度分组。但是,我试图避免安装任何东西。
我的工作正则表达式看起来像:
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']
而这个我不明白。根据我对 look behinds 的理解,这最后一个表达式应该有效。知道如何使用基本 re 模块完成此操作吗?
您可以使用:
>>> 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 由于此错误
,正则表达式引擎将不允许(?<!(?:\r|XYZ))
后视
error: look-behind requires fixed-width pattern
您可以使用 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
如果匹配的字符不是两者中的那个则控制转移到or 部分即 .
可以匹配任何字符但不匹配换行符。 +
之后非捕获组会重复整个模式一次或多次。