提取完整单词
我有一大堆现实生活中的文本,需要从中提取单词,以便输入到拼写检查器中。我希望能提取尽可能多的有意义的单词,而不是太多杂乱的东西。我知道这里有很多正则表达式高手,希望能有人帮我。
目前,我是用'[a-z]+'
来提取所有字母序列。这种方法还不错,但会带出很多无用的东西。
理想情况下,我想要一些正则表达式(不需要特别好看或高效),能够提取所有由自然单词分隔符(比如[/-_,.: ]
等)分开的字母序列,并忽略任何有非法边界的字母序列。
不过,我也很乐意只提取那些与数字不相邻的字母序列。比如'pie21'
就不会提取出'pie'
,但'http://foo.com'
会提取出['http', 'foo', 'com']
。
我尝试过lookahead
和lookbehind
的断言,但它们是按字符应用的(比如re.findall('(?<!\d)[a-z]+(?!\d)', 'pie21')
会返回'pi'
,而我希望它什么都不返回)。我尝试把字母部分包裹成一个词组((?:[a-z]+)
),但没有帮助。
更多细节:这些数据是一个电子邮件数据库,所以大部分是普通的英语和正常的数字,但偶尔会有一些像GIHQ4NWL0S5SCGBDD40ZXE5IDP13TYNEA
和AC7A21C0
这样的无用字符串,我希望能完全忽略它们。我假设任何包含数字的字母序列都是无用的。
4 个回答
关于这个:
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:就是一个匿名函数,它接收一个项目并检查它是否是一个单词(只包含大小写字母)。
编辑:添加了一些解释
如果你只使用ASCII字母,那么可以使用(并设置re.I
选项)
\b[a-z]+\b
\b
是一个单词边界锚点,它只在字母数字“单词”的开头和结尾匹配。所以 \b[a-z]+\b
可以匹配 pie
,但不能匹配 pie21
或 21pie
。
如果你想允许其他非ASCII字母,可以使用类似这样的方式:
\b[^\W\d_]+\b
这样也可以允许带重音的字符等等。你可能需要设置 re.UNICODE
选项,特别是在使用Python 2的时候,以便让 \w
这个简写可以匹配非ASCII字母。
[^\W\d_]
作为一个否定字符类,允许任何字母数字字符,但不包括数字和下划线。