如何有效地删除非ASCII字符和数字,但保留重音ASCII字符

时间:2015-11-22 01:23:34

标签: python regex unicode non-ascii-characters

我有几个这样的字符串:

s = u'awëerwq\u0645\u0631\u062d\u0628\u0627\u043c\u0438\u0440bròn 1990 23x4 + &23 \'we\' we\'s mexicqué'
s
"awëerwq مرحباмир bròn 1990 23x4 + &23 'we' we's mexicqué"

我找不到一种方法可以删除像'مرحباми'这样的不可打印的内容,但保留拉丁字符,例如'óé,......'。在我的情况下,数字(如'1990')也是不受欢迎的。我使用了来自ASCII的{​​{1}}标记,但我不知道它有什么问题,因为它删除了'óëé,......'。使用re也是同样的问题。 我不知道为什么

string.printable

鉴于ASCII表被分配了137.我期望的结果是这样的:

ord('ë')
235

然后,我想编码而不依赖于不固定的编码。

2 个答案:

答案 0 :(得分:3)

这是一种可能有用的方法(Python 3.4):

import unicodedata
def remove_nonlatin(s): 
    s = (ch for ch in s
         if unicodedata.name(ch).startswith(('LATIN', 'DIGIT', 'SPACE')))
    return ''.join(s)

>>> s = 'awëerwq\u0645\u0631\u062d\u0628\u0627\u043c\u0438\u0440bròn 1990 23x4 + &23 \'we\' we\'s mexicqué'
>>> remove_nonlatin(s)
'awëerwqbròn 1990 23x4  23 we wes mexicqué'

这将获取字符串中字符的unicode名称,并匹配名称以LATIN,DIGIT或SPACE开头的字符。

例如,这将匹配:

>>> unicodedata.name('S')
'LATIN CAPITAL LETTER S'

这不会:

>>> unicodedata.name('م')
'ARABIC LETTER MEEM'

我有理由相信拉丁字符都有以'LATIN'开头的unicode名称,因此这应该过滤掉其他编写脚本,同时保留数字和空格。标点符号没有方便的单行,因此在此示例中,感叹号等也会被过滤掉。

你可以通过使用像ord(c) < 0x250这样的东西按代码点进行过滤,尽管你可能会得到一些你不期望的东西。或者,您可以尝试按unicodedata.category进行过滤。但是,“字母”类别包含来自许多脚本的字母,因此您仍然会得到其中一些:'م'。

答案 1 :(得分:1)

  

我使用了来自re的ASCII标志,但我不知道它有什么问题,因为它删除了'óëé,......'。

我认为你的问题是错误的。 ASCII中没有字符óëé。看看这里看到所有ASCII字符的集合,看看它是如何基本的:

https://en.wikipedia.org/wiki/ASCII#ASCII_printable_code_chart

您使用的字符串似乎是Unicode,因为它可以同时支持“مرحباми”和“'óëé”。

在这种情况下,您可以使用

找到所需的字符范围

http://jrgraphix.net/research/unicode_blocks.php

并且仅包含拉丁文字符(例如,这将过滤掉阿拉伯字符)。

以下是一个例子:

import re
s = u"مرحباми123"

# prints "123" by keeping all characters from the following ranges:
# 0020 — 007F   Basic Latin
# 00A0 — 00FF   Latin-1 Supplement
# 0100 — 017F   Latin Extended-A
# 0180 — 024F   Latin Extended-B
print ''.join(re.findall(ur'[\u0020-\u007F\u00A0-\u00FF\u0100-\u017F\u0180-\u024F]+', s))