提取完整单词

9 投票
4 回答
35591 浏览
提问于 2025-04-16 16:02

我有一大堆现实生活中的文本,需要从中提取单词,以便输入到拼写检查器中。我希望能提取尽可能多的有意义的单词,而不是太多杂乱的东西。我知道这里有很多正则表达式高手,希望能有人帮我。

目前,我是用'[a-z]+'来提取所有字母序列。这种方法还不错,但会带出很多无用的东西。

理想情况下,我想要一些正则表达式(不需要特别好看或高效),能够提取所有由自然单词分隔符(比如[/-_,.: ]等)分开的字母序列,并忽略任何有非法边界的字母序列。

不过,我也很乐意只提取那些与数字不相邻的字母序列。比如'pie21'就不会提取出'pie',但'http://foo.com'会提取出['http', 'foo', 'com']

我尝试过lookaheadlookbehind的断言,但它们是按字符应用的(比如re.findall('(?<!\d)[a-z]+(?!\d)', 'pie21')会返回'pi',而我希望它什么都不返回)。我尝试把字母部分包裹成一个词组((?:[a-z]+)),但没有帮助。

更多细节:这些数据是一个电子邮件数据库,所以大部分是普通的英语和正常的数字,但偶尔会有一些像GIHQ4NWL0S5SCGBDD40ZXE5IDP13TYNEAAC7A21C0这样的无用字符串,我希望能完全忽略它们。我假设任何包含数字的字母序列都是无用的。

4 个回答

2

关于这个:

import re
yourString="pie 42 http://foo.com GIHQ4NWL0S5SCGBDD40ZXE5IDP13TYNEA  pie42"
filter (lambda x:re.match("^[a-zA-Z]+$",x),[x for x in set(re.split("[\s:/,.:]",yourString))])

注意:

  • split 是把你的字符串拆分成可能的候选项 => 返回一个“潜在单词”的列表
  • set 是用来去重的 => 把列表变成集合,这样就能去掉重复出现的项。这个步骤不是必须的。
  • filter 是用来减少候选项的数量:它会拿一个列表,对每个元素应用一个测试函数,然后返回通过测试的元素列表。在我们的例子中,测试函数是“匿名的”。
  • lambda:就是一个匿名函数,它接收一个项目并检查它是否是一个单词(只包含大小写字母)。

编辑:添加了一些解释

3

你知道什么是 单词边界 吗?(\b)。你可以用 \b 来提取单词,这个符号可以放在你想要匹配的字母前后:

\b([a-zA-Z]+)\b

比如说,这样做可以抓取完整的单词,但会在像连字符、句号、分号等符号处停止。

你可以在 Python手册 上找到 \b 这个符号和其他相关内容。

编辑 如果你想要匹配的内容前后有数字,你可以使用负向前瞻或负向后瞻:

(?!\d)   # negative look-ahead for numbers
(?<!\d)  # negative look-behind for numbers
18

如果你只使用ASCII字母,那么可以使用(并设置re.I选项)

\b[a-z]+\b

\b 是一个单词边界锚点,它只在字母数字“单词”的开头和结尾匹配。所以 \b[a-z]+\b 可以匹配 pie,但不能匹配 pie2121pie

如果你想允许其他非ASCII字母,可以使用类似这样的方式:

\b[^\W\d_]+\b

这样也可以允许带重音的字符等等。你可能需要设置 re.UNICODE 选项,特别是在使用Python 2的时候,以便让 \w 这个简写可以匹配非ASCII字母。

[^\W\d_] 作为一个否定字符类,允许任何字母数字字符,但不包括数字和下划线。

撰写回答