首页 文章

用单个空格替换非ASCII字符

提问于
浏览
191

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

def remove_non_ascii_1(text):

    return ''.join(i for i in text if ord(i)<128)

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

def remove_non_ascii_2(text):

    return re.sub(r'[^\x00-\x7F]',' ', text)

How can I replace all non-ASCII characters with a single space?

Of the myriad of similar SO questionsnone address character replacement as opposed to strippingand另外解决所有非ascii字符而非特定字符 .

6 回答

  • 186

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

    return ''.join([i if ord(i) < 128 else ' ' for i in text])
    

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

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

    re.sub(r'[^\x00-\x7F]+',' ', text)
    

    注意 + 那里 .

  • 18

    对于你来说,获得最相似的原始字符串表示我推荐the unidecode module

    from unidecode import unidecode
    def remove_non_ascii(text):
        return unidecode(unicode(text, encoding = "utf-8"))
    

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

    remove_non_ascii("Ceñía")
    Cenia
    
  • 6

    对于字符处理,请使用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'
    

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

    >>> s = 'mañana'
    >>> len(s)
    6
    >>> import unicodedata as ud
    >>> n=ud.normalize('NFD',s)
    >>> n
    'mañ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'
    
  • 1

    如果替换字符可以是'?'而不是空格,那么我建议 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(),
    ))
    

    结果:

    0.7208260721400134
    0.009975979187503592
    
  • 5

    这个如何?

    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
    
  • 35

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

    以下将删除非ascii字符:

    new_string = old_string.encode('ascii',errors='ignore')
    

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

    final_string = new_string + b' ' * (len(old_string) - len(new_string))
    

相关问题