用单个空格替换非ASCII字符

dot*_*hen 228 python unicode encoding ascii

我需要用空格替换所有非ASCII(\ x00-\x7F)字符.我很惊讶这在Python中并不容易,除非我遗漏了一些东西.以下函数只删除所有非ASCII字符:

def remove_non_ascii_1(text):

    return ''.join(i for i in text if ord(i)<128)
Run Code Online (Sandbox Code Playgroud)

并且这个用字符代码点中的字节数替换非ASCII字符和空格量(即字符被3个空格替换):

def remove_non_ascii_2(text):

    return re.sub(r'[^\x00-\x7F]',' ', text)
Run Code Online (Sandbox Code Playgroud)

如何用单个空格替换所有非ASCII字符?

无数 类似 SO 问题, 地址 的字符 替换 反对 剥离,进一步解决所有非ASCII字符不是一个特定的字符.

Mar*_*ers 226

你的''.join()表达式是过滤,删除任何非ASCII; 您可以使用条件表达式:

return ''.join([i if ord(i) < 128 else ' ' for i in text])
Run Code Online (Sandbox Code Playgroud)

这将逐个处理字符,并且每个字符仍然会替换一个空格.

您的正则表达式应该只用空格替换连续的非ASCII字符:

re.sub(r'[^\x00-\x7F]+',' ', text)
Run Code Online (Sandbox Code Playgroud)

请注意+那里.

  • @dstromberg:慢; `str.join()`*需要*一个列表(它会将值传递两次),并且生成器表达式将首先转换为一个.给它一个列表理解只是更快.见[this post](http://stackoverflow.com/a/9061024). (18认同)
  • *"`-`字符被替换为3个空格"*在问题中暗示输入是字节串(不是Unicode),因此使用Python 2(否则`''.join`将失败).如果OP希望每个Unicode代码点有一个空格,则应首先将输入解码为Unicode. (2认同)

小智 48

对于你来说,获得最相似的原始字符串表示我推荐使用unidecode模块:

from unidecode import unidecode
def remove_non_ascii(text):
    return unidecode(unicode(text, encoding = "utf-8"))
Run Code Online (Sandbox Code Playgroud)

然后你可以在字符串中使用它:

remove_non_ascii("Ceñía")
Cenia
Run Code Online (Sandbox Code Playgroud)

  • 对于Python 3,请使用:`return unidecode(str(text))` (12认同)
  • @AlvaroFuentes,自 [this](http://stackoverflow.com/questions/19877306/nameerror-global-name-unicode-is-not-defined-in-python-3) 以来,如何处理/重写 Python 3 的精彩代码)?错误:**NameError:未定义全局名称“unicode”** (5认同)

Mar*_*nen 19

对于字符处理,请使用Unicode字符串:

PythonWin 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:57:17) [MSC v.1600 64 bit (AMD64)] on win32.
>>> s='ABC??def'
>>> import re
>>> re.sub(r'[^\x00-\x7f]',r' ',s)   # Each char is a Unicode codepoint.
'ABC  def'
>>> b = s.encode('utf8')
>>> re.sub(rb'[^\x00-\x7f]',rb' ',b) # Each char is a 3-byte UTF-8 sequence.
b'ABC      def'
Run Code Online (Sandbox Code Playgroud)

但请注意,如果您的字符串包含已分解的Unicode字符(例如,单独的字符和组合重音符号),您仍会遇到问题:

>>> s = 'mañana'
>>> len(s)
6
>>> import unicodedata as ud
>>> n=ud.normalize('NFD',s)
>>> n
'man?ana'
>>> len(n)
7
>>> re.sub(r'[^\x00-\x7f]',r' ',s) # single codepoint
'ma ana'
>>> re.sub(r'[^\x00-\x7f]',r' ',n) # only combining mark replaced
'man ana'
Run Code Online (Sandbox Code Playgroud)


AXO*_*AXO 8

如果替换字符可以是'?' 而不是空格,那么我建议result = text.encode('ascii', 'replace').decode():

"""Test the performance of different non-ASCII replacement methods."""


import re
from timeit import timeit


# 10_000 is typical in the project that I'm working on and most of the text
# is going to be non-ASCII.
text = 'Æ' * 10_000


print(timeit(
    """
result = ''.join([c if ord(c) < 128 else '?' for c in text])
    """,
    number=1000,
    globals=globals(),
))

print(timeit(
    """
result = text.encode('ascii', 'replace').decode()
    """,
    number=1000,
    globals=globals(),
))
Run Code Online (Sandbox Code Playgroud)

结果:

0.7208260721400134
0.009975979187503592
Run Code Online (Sandbox Code Playgroud)


par*_*cer 7

这个如何?

def replace_trash(unicode_string):
     for i in range(0, len(unicode_string)):
         try:
             unicode_string[i].encode("ascii")
         except:
              #means it's non-ASCII
              unicode_string=unicode_string[i].replace(" ") #replacing it with a single space
     return unicode_string
Run Code Online (Sandbox Code Playgroud)

  • 虽然这相当不优雅,但它非常具有可读性。谢谢。 (2认同)

Kas*_*mvd 5

作为一种原生且高效的方法,您不需要使用ord字符或对字符进行任何循环。只需编码ascii并忽略错误。

以下将仅删除非 ascii 字符:

new_string = old_string.encode('ascii',errors='ignore')
Run Code Online (Sandbox Code Playgroud)

现在,如果您想替换已删除的字符,请执行以下操作:

final_string = new_string + b' ' * (len(old_string) - len(new_string))
Run Code Online (Sandbox Code Playgroud)

  • new_string = old_string.encode('ascii',errors='ignore').decode() (2认同)

归档时间:

查看次数:

178209 次

最近记录:

6 年,8 月 前