Python,从字符串中删除所有非字母字符

Posted

技术标签:

【中文标题】Python,从字符串中删除所有非字母字符【英文标题】:Python, remove all non-alphabet chars from string 【发布时间】:2014-04-26 14:06:01 【问题描述】:

我正在编写一个 python MapReduce 字数统计程序。问题是数据中散布着许多非字母字符,我发现这篇文章Stripping everything but alphanumeric chars from a string in Python 显示了使用正则表达式的一个很好的解决方案,但我不知道如何实现它

def mapfn(k, v):
    print v
    import re, string 
    pattern = re.compile('[\W_]+')
    v = pattern.match(v)
    print v
    for w in v.split():
        yield w, 1

恐怕我不确定如何使用库re 甚至是正则表达式。我不确定如何将正则表达式模式正确应用到传入字符串(书的行)v 以检索没有任何非字母数字字符的新行。

建议?

【问题讨论】:

v 是一本书的整行(特别是白鲸),我将逐字逐句地阅读。所以有些词的结尾可能有一个“,”,所以“indignity”不会与“indignity”对应。 Stripping everything but alphanumeric chars from a string in Python的可能重复 Lolx - 你有和我一样的面试前家庭练习吗?在 Moby Dick 中找到 50 个最常用的词并报告它们的频率。我是用 C++ 做的,IIRC @Mawg 这是我本科“云计算”课上的一个练习。 【参考方案1】:

如果您计划匹配特定的 Unicode 属性类,建议使用 PyPi regex module。这个库也被证明更稳定,尤其是处理大文本,并且在各种 Python 版本中产生一致的结果。您需要做的就是使其保持最新状态。

如果你安装它(使用pip install regexpip3 install regex),你可以使用

import regex
print ( regex.sub(r'\PL+', '', 'ABCŁąć1-2!Абв3§4“5def”') )
// => ABCŁąćАбвdef

text 中删除所有包含 1 个或多个字符的块,而不是 Unicode 字母。请参阅online Python demo。您也可以使用"".join(regex.findall(r'\pL+', 'ABCŁąć1-2!Абв3§4“5def”')) 来获得相同的结果。

在 Python re 中,为了匹配任何 Unicode 字母,可以使用 [^\W\d_] 构造 (Match any unicode letter?)。

因此,要删除所有非字母字符,您可以匹配所有字母并加入结果:

result = "".join(re.findall(r'[^\W\d_]', text))

或者,删除与[\W\d_] 模式匹配的所有字符(与[^\W\d_] 相反):

result = re.sub(r'[\W\d_]+', '', text)

请参阅regex demo online。 但是,由于 Unicode 标准在不断发展,您可能会在不同的 Python 版本中得到不一致的结果,并且与 \w 匹配的字符集将取决于 Python 版本。强烈建议使用 PyPi regex 库以获得一致的结果。

【讨论】:

【参考方案2】:

试试:

s = ''.join(filter(str.isalnum, s))

这将从字符串中取出每个字符,只保留字母数字字符并从它们构建一个字符串。

【讨论】:

这很好,因为它可以处理像Å Å Ö这样的奇怪字符【参考方案3】:

使用re.sub

import re

regex = re.compile('[^a-zA-Z]')
#First parameter is the replacement, second parameter is your input string
regex.sub('', 'ab3d*E')
#Out: 'abdE'

或者,如果您只想删除某组字符(因为在您的输入中可以使用撇号...)

regex = re.compile('[,\.!?]') #etc.

【讨论】:

嗯,我可以很好地找到它,但是删除所有非字母数字(不包括空格)的模式呢? 只需在您的收藏类中添加一个空格。即^a-zA-Z 而不仅仅是^a-zA-Z 除非你也担心换行,在这种情况下a-zA-Z \n。我试图找到一个将两者合二为一的正则表达式,但使用 \w\W 并没有给我想要的行为。如果是这种情况,您可能只需要添加 \n 啊,换行符。那就是我的问题所在,我正在将我的结果与给定的结果进行比较,但我仍然没有。我想这是我的问题!谢谢 // 嗯,我用换行符尝试了相同的结果,我想还有一个我错过了.. // Duhhh... 大写和小写... // 感谢所有的帮助,现在完美! 【参考方案4】:

最快的方法是正则表达式

#Try with regex first
t0 = timeit.timeit("""
s = r2.sub('', st)

""", setup = """
import re
r2 = re.compile(r'[^a-zA-Z0-9]', re.MULTILINE)
st = 'abcdefghijklmnopqrstuvwxyz123456789!@#$%^&*()-=_+'
""", number = 1000000)
print(t0)

#Try with join method on filter
t0 = timeit.timeit("""
s = ''.join(filter(str.isalnum, st))

""", setup = """
st = 'abcdefghijklmnopqrstuvwxyz123456789!@#$%^&*()-=_+'
""",
number = 1000000)
print(t0)

#Try with only join
t0 = timeit.timeit("""
s = ''.join(c for c in st if c.isalnum())

""", setup = """
st = 'abcdefghijklmnopqrstuvwxyz123456789!@#$%^&*()-=_+'
""", number = 1000000)
print(t0)


2.6002226710006653 Method 1 Regex
5.739747313000407 Method 2 Filter + Join
6.540099570000166 Method 3 Join

【讨论】:

【参考方案5】:

如果你不想使用正则表达式,你可以试试

''.join([i for i in s if i.isalpha()])

【讨论】:

如何加入?与 ''.join ?打印 s 只得到一个过滤器对象 哇,这就是我想要的。这考虑了汉字、平假名、片假名等。荣誉【参考方案6】:

您可以使用 re.sub() 函数删除这些字符:

>>> import re
>>> re.sub("[^a-zA-Z]+", "", "ABC12abc345def")
'ABCabcdef'

re.sub(匹配模式,替换字符串,要搜索的字符串)

"[^a-zA-Z]+" - 寻找任何不是的字符组 a-zA-z。 "" - 用“”替换匹配的字符

【讨论】:

请注意,这也会删除重音字母:ãâàéèçõ 等

以上是关于Python,从字符串中删除所有非字母字符的主要内容,如果未能解决你的问题,请参考以下文章

从 lua 字符串中删除所有非字母数字字符

Netezza 和 Regexp:如何从字符串中删除所有非字母

Python编程题35--删除字符串中的所有相邻重复项

从字符串中删除非字母数字字符(包括 ß、Ê 等)

从Python中的字符串中删除所有非数字字符

快速从字符串中删除所有非数字字符