17

我是编程新手,对不起,如果这看起来微不足道:我有一个文本,我试图使用正则表达式将其拆分为单个句子。使用该.split方法,我搜索一个点,后跟一个大写字母,例如

"\. A-Z"

但是,我需要通过以下方式细化此规则:.(dot) 前面不能有Absor S。并且如果它后跟一个大写字母 ( A-Z),如果它是一个月份名称,它应该仍然不匹配,例如January | February | March.

我尝试实施前半部分,但即使这样也没有用。我的代码是:

"( (?<!Abs)\. A-Z) | (?<!S)\. A-Z) ) "
4

5 回答 5

21

首先,我认为您可能希望将空格替换为\s+,或者\s如果它确实是一个空格(您经常会在英文文本中找到双空格)。

其次,要匹配您必须使用的大写字母[A-Z],但A-Z不会起作用(但请记住,除了A-Z...之外,可能还有其他大写字母)。

此外,我想我知道为什么这不起作用。\. [A-Z]如果前面没有Absor ,正则表达式引擎将尝试匹配S。问题是,如果它前面有S,它前面没有Abs,所以第一个模式匹配。如果前面有Abs,则前面没有S,所以第二个模式版本匹配。无论哪种方式,这些模式中的一个都将匹配,因为Abs并且S是互斥的。

您问题第一部分的模式可能是

(?<!Abs)(?<!S)(\. [A-Z])

或者

(?<!Abs)(?<!S)(\.\s+[A-Z])

(根据我的建议)

那是因为你必须避免|,如果没有它,现在的表达方式是不以 Abs 为先,也不以 S 为先。如果两者都为真,则模式匹配器将继续扫描字符串并找到您的匹配项。

为了排除月份名称,我想出了这个正则表达式:

(?<!Abs)(?<!S)(\.\s+)(?!January|February|March)[A-Z]

同样的论点也适用于消极的前瞻性模式。

于 2012-10-02T11:16:14.470 回答
6

我正在为标题中的问题添加一个简短的答案,因为它位于 Google 搜索结果的顶部:

拥有多个不同长度的负面lookbehinds的方法是将它们链接在一起,如下所示:

"(?<!1)(?<!12)(?<!123)example"

这将匹配example 2exampleand3example但不匹配1example 12exampleor 123example

于 2019-07-12T08:13:12.610 回答
1

使用nltk punkt 分词器。它可能比使用正则表达式更健壮。

>>> import nltk.data
>>> text = """
... Punkt knows that the periods in Mr. Smith and Johann S. Bach
... do not mark sentence boundaries.  And sometimes sentences
... can start with non-capitalized words.  i is a good variable
... name.
... """
>>> sent_detector = nltk.data.load('tokenizers/punkt/english.pickle')
>>> print '\n-----\n'.join(sent_detector.tokenize(text.strip()))
Punkt knows that the periods in Mr. Smith and Johann S. Bach
do not mark sentence boundaries.
-----
And sometimes sentences
can start with non-capitalized words.
-----
i is a good variable
name.
于 2012-10-02T11:13:47.813 回答
1

使用 @root 建议的 nltk 或类似工具。

要回答您的正则表达式问题:

import re
import sys

print re.split(r"(?<!Abs)(?<!S)\.\s+(?!January|February|March)(?=[A-Z])",
               sys.stdin.read())

输入

First. Second. January. Third. Abs. Forth. S. Fifth.
S. Sixth. ABs. Eighth

输出

['First', 'Second. January', 'Third', 'Abs. Forth', 'S. Fifth',
 'S. Sixth', 'ABs', 'Eighth']
于 2012-10-02T11:41:00.163 回答
-2

您可以使用设置 []。

'(?<![1,2,3]例子)'

This would not match 1example, 2example, 3example.

于 2020-06-11T08:43:48.530 回答