Reemplazar caracteres que no sean ASCII con un solo espacio
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.
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í.
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")
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'