Eliminar caracteres no ascii en cadena

89
var str="INFO] :谷���新道, ひば���ヶ丘2丁���, ひばりヶ���, 東久留米市 (Higashikurume)";

y necesito eliminar todos los caracteres no ascii de la cadena,

significa que str solo contiene "INFO] (Higashikurume)";

Dev
fuente

Respuestas:

229

ASCII está en el rango de 0 a 127, entonces:

str.replace(/[^\x00-\x7F]/g, "");
Zaffy
fuente
8
@AlexanderMills Busque una tabla ascii: puede ver que solo los caracteres que tienen un valor de cero a 127 son válidos. (0x7F es 127 en hexadecimal). Este código coincide con todos los caracteres que no están en el rango ascii y los elimina.
Zaffy
31

También se puede hacer con una afirmación positiva de eliminación, como esta:

textContent = textContent.replace(/[\u{0080}-\u{FFFF}]/gu,"");

Esto usa unicode. En Javascript, al expresar unicode para una expresión regular, los caracteres se especifican con la secuencia de escape \u{xxxx}pero también 'u'debe estar presente la bandera ; tenga en cuenta que la expresión regular tiene banderas 'gu'.

Llamé a esto una "afirmación positiva de eliminación" en el sentido de que una afirmación "positiva" expresa qué caracteres eliminar, mientras que una afirmación "negativa" expresa qué letras no eliminar. En muchos contextos, la afirmación negativa, como se indica en las respuestas anteriores, puede resultar más sugerente para el lector. El circunflejo " ^" dice "no" y el rango \x00-\x7Fdice "ascii", por lo que los dos juntos dicen "no ascii".

textContent = textContent.replace(/[^\x00-\x7F]/g,"");

Esa es una gran solución para los hablantes de inglés que solo se preocupan por el idioma inglés, y también es una buena respuesta para la pregunta original. Pero en un contexto más general, no siempre se puede aceptar el sesgo cultural de asumir que "todo lo que no es ascii es malo". Para contextos en los que se usa no ascii, pero ocasionalmente es necesario eliminarlo, la afirmación positiva de Unicode es más adecuada.

Una buena indicación de que los caracteres no imprimibles de ancho cero están incrustados en una cadena es cuando la propiedad "longitud" de la cadena es positiva (distinta de cero), pero parece (es decir, se imprime como) una cadena vacía. Por ejemplo, apareció esto en el depurador de Chrome, para una variable llamada "textContent":

> textContent
""
> textContent.length
7

Esto me impulsó a querer ver qué había en esa cadena.

> encodeURI(textContent)
"%E2%80%8B%E2%80%8B%E2%80%8B%E2%80%8B%E2%80%8B%E2%80%8B%E2%80%8B"

Esta secuencia de bytes parece pertenecer a la familia de algunos caracteres Unicode que los procesadores de texto insertan en los documentos y luego encuentran su camino hacia los campos de datos. Por lo general, estos símbolos aparecen al final de un documento. El espacio de ancho cero "%E2%80%8B"puede ser insertado por CK-Editor (CKEditor).

encodeURI()  UTF-8     Unicode  html     Meaning
-----------  --------  -------  -------  -------------------
"%E2%80%8B"  EC 80 8B  U 200B   ​  zero-width-space
"%E2%80%8E"  EC 80 8E  U 200E   ‎  left-to-right-mark
"%E2%80%8F"  EC 80 8F  U 200F   ‏  right-to-left-mark

Algunas referencias sobre esos:

http://www.fileformat.info/info/unicode/char/200B/index.htm

https://en.wikipedia.org/wiki/Left-to-right_mark

Tenga en cuenta que, aunque la codificación del carácter incrustado es UTF-8, la codificación de la expresión regular no lo es. Aunque el carácter está incrustado en la cadena como tres bytes (en mi caso) de UTF-8, las instrucciones en la expresión regular deben usar Unicode de dos bytes. De hecho, UTF-8 puede tener hasta cuatro bytes de longitud; es menos compacto que Unicode porque usa el bit alto (o bits) para escapar de la codificación ascii estándar. Eso se explica aquí:

https://en.wikipedia.org/wiki/UTF-8

IAM_AL_X
fuente
3
textContent = textContent.replace(/[\u{0080}-\u{FFFF}]/gu,"");no funciona en IE (al menos IE 11). Falla con el error: SCRIPT5021 : rango no válido en el conjunto de caracteres
Andrey Sorich
14

Puede usar la siguiente expresión regular para reemplazar caracteres no ASCII

str = str.replace(/[^A-Za-z 0-9 \.,\?""!@#\$%\^&\*\(\)-_=\+;:<>\/\\\|\}\{\[\]`~]*/g, '')

Sin embargo, tenga en cuenta que los espacios, dos puntos y comas son todos ASCII válidos, por lo que el resultado será

> str
"INFO] :, , ,  (Higashikurume)"
Chris Taylor
fuente
No soy bueno con las expresiones regulares, pero sé que el método .replace () toma lo que desea reemplazar y reemplaza el segundo parámetro como .replace ('reemplazar este texto', 'con este texto'). Entonces, ¿qué parte de eso dice hacer lo contrario y dejar los caracteres ascii y eliminar los demás? Gracias.
NicoM
2
@NicoM Caracteres []significa cualquier carácter pero [^]significa lo contrario: coincide con cualquier carácter que no esté entre corchetes.
Zaffy
10

Ninguna de estas respuestas maneja apropiadamente pestañas, nuevas líneas, retornos de carro y algunas no manejan ASCII extendido y Unicode. Esto MANTENDRÁ pestañas y nuevas líneas, pero eliminará los caracteres de control y todo lo que esté fuera del conjunto ASCII. Haga clic en el botón "Ejecutar este fragmento de código" para probar. Hay un nuevo javascript en camino, por lo que en el futuro (¿2020+?) Es posible que tenga que hacerlo, \u{FFFFF}pero aún no

console.log("line 1\nline2 \n\ttabbed\nF̸̡̢͓̳̜̪̟̳̠̻̖͐̂̍̅̔̂͋͂͐l̸̢̹̣̤̙͚̱͓̖̹̻̣͇͗͂̃̈͝a̸̢̡̬͕͕̰̖͍̮̪̬̍̏̎̕͘ͅv̸̢̛̠̟̄̿i̵̮͌̑ǫ̶̖͓͎̝͈̰̹̫͚͓̠̜̓̈́̇̆̑͜ͅ".replace(/[\x00-\x08\x0E-\x1F\x7F-\uFFFF]/g, ''))

Jonathan
fuente
es una buena expresión regular, pero también elimina acentos y emojis. No estoy seguro de cómo mejorar esta expresión regular para cubrir estos casos.
Julio Vedovatto
Para cualquiera que busque una posible solución para eliminar Angular window.atob y DOMSanitizer.bypassSecurity ... caracteres no válidos (ya sea% 80, \ uFFFF o espacios en blanco inexplicables) al convertir a base64, esta es una solución que funciona
B. León
9

Para usar ASCII con acentos:

var str = str.replace(/[^\x00-\xFF]/g, "");
Eolia
fuente
¡Brillante! Maneja valores ascii por encima de 127 que otras respuestas descartan.
user3413723
¿Qué tal el texto alternativo con acentos ... como altcodeunicode.com/alt-codes-letter-e-with-accents ?
Apilado