Reemplazar caracteres que no sean ASCII con un solo espacio

Resuelto dotancohen asked hace 10 años • 12 respuestas

Necesito reemplazar todos los caracteres que no sean ASCII (\x00-\x7F) con un espacio. Me sorprende que esto no sea tan fácil en Python, a menos que me esté perdiendo algo. La siguiente función simplemente elimina todos los caracteres que no sean ASCII:

def remove_non_ascii_1(text):

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

Y éste reemplaza los caracteres que no son ASCII con la cantidad de espacios según la cantidad de bytes en el punto del código de carácter (es decir, el carácter se reemplaza con 3 espacios):

def remove_non_ascii_2(text):

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

¿Cómo puedo reemplazar todos los caracteres que no son ASCII con un solo espacio?

De la gran cantidad de preguntas SO similares , ninguna aborda el reemplazo de caracteres en lugar de la eliminación y , además, aborda todos los caracteres que no son ASCII, no un carácter específico.

dotancohen avatar Nov 20 '13 01:11 dotancohen
Aceptado

Su ''.join()expresión está filtrando , eliminando todo lo que no sea ASCII; podrías usar una expresión condicional en su lugar:

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

Esto maneja los caracteres uno por uno y aún usaría un espacio por cada carácter reemplazado.

Su expresión regular debería simplemente reemplazar caracteres consecutivos que no sean ASCII con un espacio:

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

Tenga en cuenta el +allí.

Martijn Pieters avatar Nov 19 '2013 18:11 Martijn Pieters

Para obtener la representación más parecida de su cadena original, le recomiendo el módulo unidecode :

Pitón 2

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

Entonces puedes usarlo en una cadena:

remove_non_ascii("Ceñía")
Cenia

Pitón 3

from unidecode import unidecode
unidecode("Ceñía")
Alvaro Fuentes avatar Feb 18 '2016 20:02 Alvaro Fuentes

Para el procesamiento de caracteres , utilice cadenas 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'

Pero tenga en cuenta que seguirá teniendo un problema si su cadena contiene caracteres Unicode descompuestos (caracteres separados y combinación de acentos, por ejemplo):

>>> 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'
Mark Tolonen avatar Nov 19 '2013 18:11 Mark Tolonen