Python 正则表达式 A|B|C 匹配 C,即使 B 应该匹配
Python regex A|B|C matches C even though B should match
我已经在这个问题上坐了几个小时了,我真的不知道了......
本质上,我有一个 A|B|C - 类型分隔的正则表达式,并且无论出于何种原因 C 匹配 B,即使应该从左到右测试各个正则表达式并以非贪婪的方式停止(即一次匹配已找到,其他正则表达式不再测试)。
这是我的代码:
text = 'Patients with end stage heart failure fall into stage D of the ABCD classification of the American College of Cardiology (ACC)/American Heart Association (AHA), and class III–IV of the New York Heart Association (NYHA) functional classification; they are characterised by advanced structural heart disease and pronounced symptoms of heart failure at rest or upon minimal physical exertion, despite maximal medical treatment according to current guidelines.'
expansion = "American Heart Association"
re_exp = re.compile(expansion + "|" + r"(?<=\W)" + expansion + "|"\
+ expansion.split()[0] + r"[-\s].*?\s*?" + expansion.split()[-1])
m = re_exp.search(text)
print(m.group(0))
我想让正则表达式找到“扩展”字符串。在我的数据集中,有时文本会稍微编辑扩展字符串,例如在主要名词之间添加冠词或介词,如“for”或“the”。这就是为什么我首先尝试按原样匹配字符串,然后如果它在任何非单词字符之后尝试匹配它(即括号,或者像上面的示例一样,一大堆东西 space 被省略了),最后,我只是使用完整的通配符来查找字符串,方法是搜索字符串的开头和结尾,中间有通配符。
无论哪种方式,对于上面的示例,我都希望得到以下输出:
American Heart Association
但我得到的是
American College of Cardiology (ACC)/American Heart Association
这是最终正则表达式的匹配项。
如果我删除最后的正则表达式或只调用 re.findall(r"(?<=\W)"+ expansion, text)
,我会得到我想要的输出,这意味着正则表达式实际上匹配正确。
什么给了?
所以 re.findall(r"(?<=\W)"+ expansion, text)
有效,因为匹配之前是一个非单词字符(表示为 \w
),“/”。您的正则表达式将匹配“American [whatever random stuff here] Heart Association”。这意味着您先匹配“美国心脏病学会 (ACC)/美国心脏协会”,然后再匹配内部字符串“美国心脏协会”。例如。如果您删除了字符串中的第一个“American”,您将通过正则表达式获得您正在寻找的匹配项。
您需要对正则表达式进行更严格的限制,以排除此类情况。
正则表达式如下所示:
American Heart Association|(?<=\W)American Heart Association|American[-\s].*?\s*?Association
前 2 个备选方案匹配相同的文本,只有第二个备选方案前面有正向回顾。
您可以省略第二个选择,因为没有任何断言的第一个选择已经匹配它,或者如果第一个不匹配,第二部分也不会匹配它。
由于模式从左到右匹配,遇到第一次出现American
,第一个和第二个备选方案无法匹配American College of Cardiology
。
然后第三次交替可以匹配它,并且由于.*?
它可以延伸到第一次出现Association。
例如,您可能会使用 negated character class:
排除要匹配的可能字符
\bAmerican\b[^/,.]*\bAssociation\b
或者您可以使用 方法来不允许在第一部分和最后一部分之间使用特定的单词:
\bAmerican\b(?:(?!American\b|Association\b).)*\bHeart Association\b
我已经在这个问题上坐了几个小时了,我真的不知道了...... 本质上,我有一个 A|B|C - 类型分隔的正则表达式,并且无论出于何种原因 C 匹配 B,即使应该从左到右测试各个正则表达式并以非贪婪的方式停止(即一次匹配已找到,其他正则表达式不再测试)。
这是我的代码:
text = 'Patients with end stage heart failure fall into stage D of the ABCD classification of the American College of Cardiology (ACC)/American Heart Association (AHA), and class III–IV of the New York Heart Association (NYHA) functional classification; they are characterised by advanced structural heart disease and pronounced symptoms of heart failure at rest or upon minimal physical exertion, despite maximal medical treatment according to current guidelines.'
expansion = "American Heart Association"
re_exp = re.compile(expansion + "|" + r"(?<=\W)" + expansion + "|"\
+ expansion.split()[0] + r"[-\s].*?\s*?" + expansion.split()[-1])
m = re_exp.search(text)
print(m.group(0))
我想让正则表达式找到“扩展”字符串。在我的数据集中,有时文本会稍微编辑扩展字符串,例如在主要名词之间添加冠词或介词,如“for”或“the”。这就是为什么我首先尝试按原样匹配字符串,然后如果它在任何非单词字符之后尝试匹配它(即括号,或者像上面的示例一样,一大堆东西 space 被省略了),最后,我只是使用完整的通配符来查找字符串,方法是搜索字符串的开头和结尾,中间有通配符。
无论哪种方式,对于上面的示例,我都希望得到以下输出:
American Heart Association
但我得到的是
American College of Cardiology (ACC)/American Heart Association
这是最终正则表达式的匹配项。
如果我删除最后的正则表达式或只调用 re.findall(r"(?<=\W)"+ expansion, text)
,我会得到我想要的输出,这意味着正则表达式实际上匹配正确。
什么给了?
所以 re.findall(r"(?<=\W)"+ expansion, text)
有效,因为匹配之前是一个非单词字符(表示为 \w
),“/”。您的正则表达式将匹配“American [whatever random stuff here] Heart Association”。这意味着您先匹配“美国心脏病学会 (ACC)/美国心脏协会”,然后再匹配内部字符串“美国心脏协会”。例如。如果您删除了字符串中的第一个“American”,您将通过正则表达式获得您正在寻找的匹配项。
您需要对正则表达式进行更严格的限制,以排除此类情况。
正则表达式如下所示:
American Heart Association|(?<=\W)American Heart Association|American[-\s].*?\s*?Association
前 2 个备选方案匹配相同的文本,只有第二个备选方案前面有正向回顾。
您可以省略第二个选择,因为没有任何断言的第一个选择已经匹配它,或者如果第一个不匹配,第二部分也不会匹配它。
由于模式从左到右匹配,遇到第一次出现American
,第一个和第二个备选方案无法匹配American College of Cardiology
。
然后第三次交替可以匹配它,并且由于.*?
它可以延伸到第一次出现Association。
例如,您可能会使用 negated character class:
排除要匹配的可能字符\bAmerican\b[^/,.]*\bAssociation\b
或者您可以使用
\bAmerican\b(?:(?!American\b|Association\b).)*\bHeart Association\b