【问题标题】:How do I append a list of negative lookbehinds to a python regular expression?如何将负面后视列表附加到 python 正则表达式?
【发布时间】:2013-01-28 19:42:56
【问题描述】:

我正在尝试使用 regex split 将段落拆分为句子,并且我正在尝试使用此处发布的第二个答案: a Regex for extracting sentence from a paragraph in python

但我有一个缩写列表,即使有句号,我也不想在句子结尾。但我不知道如何正确地将其附加到该正则表达式中。我正在从一个文件中读取缩写词,该文件包含诸如 Mr. Ms. Dr. St. 之类的术语(每行一个)。

【问题讨论】:

    标签: python regex


    【解决方案1】:

    简短回答:您不能,除非所有后向断言都具有相同的固定宽度(在您的情况下它们可能不是;您的示例仅包含两个字母的缩写,但 Mrs. 会破坏您的正则表达式)。

    这是当前 Python 正则表达式引擎的限制。

    更长的答案:

    可以编写一个像(?s)(?<!.Mr|Mrs|.Ms|.St)\. 这样的正则表达式,用尽可能多的.s 填充lookbehind 断言的每个交替部分,以使它们都具有相同的宽度。但是,这在某些情况下会失败,例如当段落以 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."]
    

    【讨论】:

    • 我只能使用python标准库。那么有没有其他方法可以在不使用lookbehinds的情况下考虑缩写?
    • “这是当前 Python 正则表达式引擎的一个限制。” – 关于这个限制,你有什么要读的吗?
    • @poke:docs 读作:“(?<=...):如果字符串中的当前位置前面有一个在当前位置结束的 ... 匹配,则匹配。这称为肯定的后向断言。(?<=abc)def 将在 abcdef 中找到匹配项,因为后向将备份 3 个字符并检查包含的模式是否匹配。包含的模式必须只匹配某个固定长度的字符串,这意味着 abc 或允许a|b,但不允许a*a{3,4}。"
    • @TimPietzcker:可以对固定文本列表进行后视(在某种程度上,有一定的限制)。
    【解决方案2】:

    我不直接回答你的问题,但这篇文章应该包含足够的信息,以便你为你的问题编写一个有效的正则表达式。

    可以附加负面回顾列表。请记住,look-behinds 是零宽度的,这意味着您可以将任意数量的look-behinds 放在一起,并且您仍然从同一位置进行look-behind。只要您不需要在后视中使用“许多”量词(例如*+{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,但它不适用于更一般的情况。

    【讨论】:

    • 我已将我的一长串文字文本格式化为一个长字符串,如下所示: (?
    • @user2017502:使用它时看看问题。 Mr.__X 的情况将失败(_ 是空格 - . 和名称之间有 2 个空格)
    猜你喜欢
    • 1970-01-01
    • 2016-02-08
    • 2021-06-02
    • 1970-01-01
    • 1970-01-01
    • 2016-03-18
    • 1970-01-01
    • 2017-10-12
    • 2014-10-15
    相关资源
    最近更新 更多