python - python 正则表达式中负后向限制的解决方法
问题描述
我正在编写一个正则表达式来识别文本中的问题,但前提是在我感兴趣的短语之前的 n=3 个单词内没有否定。这是我到目前为止所拥有的:
regex = r'''(?ix) # case insensitive, verbose mode
\s+?
(?<!(not|no|never)){1,3} # if this is within 3 words, you do not match, negative lookbehind
\s+?
(a|the|any|my|your) # articles
\s+?
(issue|issues|problem|problems) # words of interest
'''
应该匹配:
matches = [
"a problem",
"the issue",
"any of the issues",
"not even close to being your issue",
]
不应该匹配:
non_matches = [
"not a problem",
"never your problem",
"not the issue",
"not overwhelmingly your issue",
"not too close your issue"
]
如果我在没有负面后视的情况下运行:
regex2 = r'''(?ix) # case insensitive, verbose
(a|the|any|my|your) # articles
\s+?
(issue|issues|problem|problems) # words of interest
'''
我得到正确的正面匹配。
>>> for p in matches:
... print(re.findall(regex2, p))
[('a', 'problem')]
[('the', 'issue')]
[('the', 'issue')]
[('your', 'issue')]
但是,如果我包括为了正确排除否定匹配而需要的否定前瞻,我会得到:
re.error: look-behind requires fixed-width pattern
我知道这只是 python 正则表达式引擎的一个限制,但是在这种情况下常用的适当解决方法是什么?有没有一种简单的方法可以将 0、1、2、3 模式组合在一起来处理它?还有什么?
解决方案
您可以安装 PyPi 正则表达式模块并忘记后向模式限制。
import regex
rx = r'''(?ix) # case insensitive, verbose mode
(?<!\b(?:not|no|never)(?:\s+\S+){0,2}\s+) # if this is within 3 words, you do not match, negative lookbehind
(a|the|any|my|your) # articles
\s+
(issue|issues|problem|problems)\b # words of interest
'''
接着
for p in matches:
print(regex.findall(rx, p))
# [('a', 'problem')]
# [('the', 'issue')]
# [('the', 'issues')]
# [('your', 'issue')]
for p in non_matches:
print(regex.findall(rx, p))
# []
# []
# []
# []
# []
请参阅Python 演示。
笔记:
(?<!\b(?:not|no|never)(?:\s+\S+){0,2}\s+)
是一个否定的向后查找,如果当前位置前面紧跟一个完整的 wordnot
,no
或者never
然后有零个、一个或两个重复的一个或多个空格,后跟一个或多个非空格,然后是一个或多个空格,则匹配失败。因此,总而言之,负面词最多可以出现 3 个远离感兴趣词的词。(?:...)
在不需要提取的模式部分周围使用非捕获组,如果捕获组在模式中定义,则始终只返回捕获re.findall
。regex.findall
否则,您将需要一种.finditer
方法。- 注意
(issue|issues|problem|problems)\b
:末尾的单词边界让正则表达式引擎将这些单词作为整个单词进行匹配,如果存在issues
,它将完整返回该单词。如果您不使用\b
并且仍然希望获得[('the', 'issues')]
第三个matches
字符串的结果,则需要将issues
替代项放在第一个替代项之前,issue
因为第一个替代项匹配“获胜”,其余的不尝试。
推荐阅读
- tailwind-css - 如何使用tailwindcss进行超小型设备设计?
- python-3.x - 如何使不和谐机器人只完成一次命令?
- django - 当我打开模型时,会自动替换一个字段值
- python - Python3 - RtMidi - 输入回调不起作用
- php - Laravel:在 Trix 编辑器中上传图像时不支持获取请求。虽然方法是 POST
- mysql - 无法连接到 mysql 工作台中的本地主机
- java - 如何从字符串中提取子字符串直到换行符
- reactjs - 更改 react-data-table-component 中的默认文本
- java - 多次调整大小时,带有 autoSizeText 的 TextView 无法正常工作
- angular - 订阅元素位置的更改检测