我有一大堆真实世界的文本,我需要从中提取单词输入到拼写检查器中。我想提取尽可能多的有意义的单词,而不会有太多的噪音。我知道这里有很多正则表达式忍者,所以希望有人能帮助我。
目前我用'[a-z]+'
提取所有字母序列。这是一个不错的近似,但是它拖出了很多垃圾。
理想情况下,我想要一些正则表达式(不必漂亮或高效),提取所有由自然词分隔符(如[/-_,.: ]
等)分隔的字母序列,并忽略任何具有非法边界的字母序列。
然而,我也很高兴能够获得所有不与数字相邻的字母序列。因此,例如'pie21'
不会提取'pie'
,但'http://foo.com'
会提取['http', 'foo', 'com']
。
我尝试了lookahead
和lookbehind
断言,但它们是按字符应用的(例如,当我希望re.findall('(?<!d)[a-z]+(?!d)', 'pie21')
不返回任何内容时,它将返回'pi'
)。我尝试将alpha部分包装为术语((?:[a-z]+)
),但没有帮助。
更多细节:数据是一个电子邮件数据库,所以它主要是普通数字的普通英语,但偶尔有垃圾字符串,如GIHQ4NWL0S5SCGBDD40ZXE5IDP13TYNEA
和AC7A21C0
,我想完全忽略。
如果您将自己限制为ASCII字母,则使用(带re.I
选项集)
b[a-z]+b
b
是一个词边界锚,只匹配字母数字"words"的开头和结尾。所以b[a-z]+b
匹配pie
,但不匹配pie21
或21pie
。
也允许其他非ascii字母,您可以使用如下命令:
b[^Wd_]+b
也允许重音字符等。您可能需要设置re.UNICODE
选项,特别是在使用Python 2时,以便允许w
速记匹配非ascii字母。
[^Wd_]
作为一个否定的字符类,允许除数字和下划线以外的任何字母数字字符。
你熟悉单词边界吗?( b
)。您可以在序列周围使用b
提取单词,并在:
b([a-zA-Z]+)b
例如,这将捕获整个单词,但仅限于标记,如连字符,句号,分号等。
您可以在python手册
中查看b
序列和其他序列。EDIT另外,如果你正在查找匹配之后或之前的数字,你可以使用否定的向前看/向后看:
(?!d) # negative look-ahead for numbers
(?<!d) # negative look-behind for numbers
怎么样:
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进行唯一性过滤=>转换set中的列表,从而删除出现多次的条目。
- filter减少候选元素的数量:接受一个列表,对每个元素应用一个测试函数,并返回一个通过测试的元素列表。在我们的例子中,测试函数是"anonymous"
- lambda:匿名函数,获取一个项目并检查它是否是一个单词(只有大写或小写字母)
EDIT:添加了一些解释
示例代码
print re.search(ur'(?u)риветb', ur'Привет')
print re.search(ur'(?u)bриветb', ur'Привет')
或
s = ur"abcd ААБВ"
import re
rx1 = re.compile(ur"(?u)АБВ")
rx2 = re.compile(ur"(?u)АБВb")
rx3 = re.compile(ur"(?u)bАБВb")
print rx1.findall(s)
print rx2.findall(s)
print rx3.findall(s)