Necesito reemplazar todos los caracteres que no sean ASCII (\ x00- \ x7F) con un espacio. Me sorprende que esto no sea fácil en Python, a menos que me falte algo. La siguiente función simplemente elimina todos los caracteres que no son ASCII:
def remove_non_ascii_1(text):
return ''.join(i for i in text if ord(i)<128)
Y este reemplaza los caracteres no ASCII con la cantidad de espacios según la cantidad de bytes en el punto de código de caracteres (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 no ASCII con un solo espacio?
De la miríada de preguntas SO similares , ninguna aborda el reemplazo de caracteres en lugar de la eliminación , y adicionalmente aborda todos los caracteres no ascii que no son un carácter específico.
–
. Es este chico .Respuestas:
Su
''.join()
expresión es filtrar , eliminar todo lo que no sea ASCII; podrías usar una expresión condicional en su lugar:Esto maneja los caracteres uno por uno y aún usaría un espacio por carácter reemplazado.
Su expresión regular debería reemplazar los caracteres no ASCII consecutivos con un espacio:
Tenga en cuenta el
+
allí.fuente
str.join()
necesita una lista (pasará los valores dos veces) y una expresión generadora se convertirá primero en una. Darle una lista de comprensión es simplemente más rápido. Ver este post .–
carácter se reemplaza con 3 espacios" en la pregunta implica que la entrada es una cadena de bytes (no Unicode) y, por lo tanto, se usa Python 2 (de lo contrario''.join
, fallaría). Si OP quiere un solo espacio por punto de código Unicode, entonces la entrada debe decodificarse primero en Unicode.Para que obtenga la representación más parecida de su cadena original, le recomiendo el módulo unidecode :
Entonces puedes usarlo en una cadena:
fuente
דותן
. Sin embargo, en el sentido general, esto es genial, ¡gracias!Para el procesamiento de caracteres , use cadenas Unicode:
Pero tenga en cuenta que todavía tendrá un problema si su cadena contiene caracteres Unicode descompuestos (caracteres separados y combinando marcas de acento, por ejemplo):
fuente
ud.normalize('NFC',s)
para combinar marcas, pero no todas las combinaciones de combinación están representadas por puntos de código únicos. Necesitarías una solución más inteligente mirandoud.category()
el personaje.\X
(grupo de grafemas extendido) regex (soportado por elregex
módulo) permite iterar sobre dichos caracteres (nota: "los grafemas no necesariamente combinan secuencias de caracteres, y la combinación de secuencias de caracteres no son necesariamente grafemas" ).Si el personaje de reemplazo puede ser '?' en lugar de un espacio, entonces sugeriría
result = text.encode('ascii', 'replace').decode()
:Resultados:
fuente
¿Qué hay de este?
fuente
Como enfoque nativo y eficiente, no necesita usar
ord
ni ningún ciclo sobre los caracteres. Simplemente codifiqueascii
e ignore los errores.Lo siguiente solo eliminará los caracteres que no sean ascii:
Ahora, si desea reemplazar los caracteres eliminados, haga lo siguiente:
fuente
encode
devolverá una cadena de bytes, así que tenlo en cuenta. Además, este método no eliminará caracteres como la nueva línea.Potencialmente para una pregunta diferente, pero estoy proporcionando mi versión de la respuesta de @ Alvero (usando unidecode). Quiero hacer una franja "regular" en mis cadenas, es decir, el principio y el final de mi cadena para los espacios en blanco, y luego reemplazar solo otros caracteres de espacios en blanco con un espacio "normal", es decir
a
,
Primero reemplazamos todos los espacios no Unicode con un espacio regular (y lo unimos de nuevo),
Y luego lo dividimos nuevamente, con la división normal de Python, y despojamos cada "bit",
Y finalmente, únete a ellos de nuevo, pero solo si la cadena pasa una
if
prueba,Y con eso,
safely_stripped('ㅤㅤㅤㅤCeñíaㅤmañanaㅤㅤㅤㅤ')
vuelve correctamente'Ceñía mañana'
.fuente