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

How to efficiently remove non-ASCII characters and numbers, but keep accented 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é"

我找不到删除非原则的方法table,例如“مرحباми”,但保留拉丁字符,例如“óé,...”。在我的情况下,数字(如“1990”)也是不可取的。我使用了 re 中的 ASCII 标志,但我不知道这有什么问题,因为它删除了 'óëé,...'。使用 string.printable 也是同样的问题。 不知道为什么

ord('ë')
235

鉴于 ASCII table 它被分配了 137。我期望的结果是这样的:

x = some_method(s)
"awëerwq bròn 23x4 we we s mexicqué" 

那么,我想在不依赖不固定编码的情况下进行编码。

I have used ASCII flag from re but I don't know what's wrong with that because it removes 'óëé,...'.

我觉得你问错了。 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))

这里有一个可能有用的方法 (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 进行过滤。但是,'letter' 类别包含来自许多脚本的字母,因此您最终仍会得到其中一些:'م'。