我正在尝试使用 regex split 将段落拆分为句子,并且我正在尝试使用此处发布的第二个答案: a Regex for extracting sentence from a paragraph in python
但是我有一个缩写列表,即使有句号,我也不想结束句子。但我不知道如何正确地将其附加到该正则表达式中。我正在从一个包含诸如 Mr. Ms. Dr. St. 之类的术语的文件中读取缩写词(每行一个)。
我正在尝试使用 regex split 将段落拆分为句子,并且我正在尝试使用此处发布的第二个答案: a Regex for extracting sentence from a paragraph in python
但是我有一个缩写列表,即使有句号,我也不想结束句子。但我不知道如何正确地将其附加到该正则表达式中。我正在从一个包含诸如 Mr. Ms. Dr. St. 之类的术语的文件中读取缩写词(每行一个)。
简短的回答:你不能,除非所有后向断言都具有相同的固定宽度(在你的情况下它们可能不是;你的例子只包含两个字母的缩写,但Mrs.
会破坏你的正则表达式)。
这是当前 Python 正则表达式引擎的限制。
更长的答案:
您可以编写一个正则表达式,如(?s)(?<!.Mr|Mrs|.Ms|.St)\.
,用尽可能多的 s 填充后向断言的每个交替部分,.
以使它们都具有相同的宽度。但是,这在某些情况下会失败,例如当段落以 . 开头时Mr.
。
无论如何,您在这里没有使用正确的工具。更好地使用为这项工作设计的工具,例如Natural Language Toolkit。
如果您坚持使用正则表达式(太糟糕了!),那么您可以尝试使用一种findall()
方法而不是split()
:
(?:(?:\b(?:Mr|Ms|Dr|Mrs|St)\.)|[^.])+\.\s*
.
将匹配以(可选地后跟空格)结尾的句子,并且可能不包含点,除非前面是允许的缩写之一。
>>> import re
>>> s = "My name is Mr. T. I pity the fool who's not on the A-Team."
>>> re.findall(r"(?:(?:\b(?:Mr|Ms|Dr|Mrs|St)\.)|[^.])+\.\s*", s)
['My name is Mr. T. ', "I pity the fool who's not on the A-Team."]
我没有直接回答您的问题,但这篇文章应该包含足够的信息,以便您为您的问题编写一个有效的正则表达式。
您可以附加负面回顾列表。请记住,look-behinds 是零宽度的,这意味着您可以将任意数量的look-behinds 放在一起,并且您仍然从同一位置进行look-behinds。只要您不需要在后视中使用“许多”量词(例如,、、*
)+
,{n,}
一切都应该没问题(?)。
所以正则表达式可以这样构造:
(?<!list )(?<!of )(?<!words )(?<!not )(?<!allowed )(?<!to )(?<!precede )pattern\w+
这有点太冗长了。无论如何,我写这篇文章只是为了证明可以回顾固定字符串的列表。
示例运行:
>>> s = 'something patterning of patterned crap patternon not patterner, not allowed patternes to patternsses, patternet'
>>> re.findall(r'(?<!list )(?<!of )(?<!words )(?<!not )(?<!allowed )(?<!to )(?<!precede )pattern\w+', s)
['patterning', 'patternon', 'patternet']
但是,使用look-behind 有一个问题。如果黑名单文本和匹配模式的文本之间存在动态数量的空格,则上面的正则表达式将失败。我真的怀疑是否存在修改正则表达式的方法,以便它适用于上述情况,同时保持后视。(您总是可以将连续的空格替换为 1,但它不适用于更一般的情况)。