special - ¿Cómo eliminar los caracteres UTF-8 no válidos de una cadena de JavaScript?
javascript unicode characters table (5)
Error simple, gran efecto:
strTest = strTest.replace(/your regex here/g, "$1");
// ----------------------------------------^
sin el indicador "global", la sustitución se produce solo para la primera coincidencia.
Nota al margen: para eliminar cualquier carácter que no cumpla con algún tipo de condición compleja, como caer en un conjunto de ciertos rangos de caracteres Unicode, puede usar lookahead negativo:
var re = /(?![/x00-/x7F]|[/xC0-/xDF][/x80-/xBF]|[/xE0-/xEF][/x80-/xBF]{2}|[/xF0-/xF7][/x80-/xBF]{3})./g;
strTest = strTest.replace(re, "")
donde re
lee como
(?! # negative look-ahead: a position *not followed by*: […] # any allowed character range from above ) # end lookahead . # match this character (only if previous condition is met!)
Me gustaría eliminar todos los caracteres UTF-8 no válidos de una cadena en JavaScript. He intentado con este JavaScript:
strTest = strTest.replace(/([/x00-/x7F]|[/xC0-/xDF][/x80-/xBF]|[/xE0-/xEF][/x80-/xBF]{2}|[/xF0-/xF7][/x80-/xBF]{3})|./g, "$1");
Parece que la expresión regular de validación UTF-8 que se describe aquí (enlace eliminado) es más completa y la adapté de la misma manera como:
strTest = strTest.replace(/([/x09/x0A/x0D/x20-/x7E]|[/xC2-/xDF][/x80-/xBF]|/xE0[/xA0-/xBF][/x80-/xBF]|[/xE1-/xEC/xEE/xEF][/x80-/xBF]{2}|/xED[/x80-/x9F][/x80-/xBF]|/xF0[/x90-/xBF][/x80-/xBF]{2}|[/xF1-/xF3][/x80-/xBF]{3}|/xF4[/x80-/x8F][/x80-/xBF]{2})|./g, "$1");
Ambas piezas de código parecen permitir el ingreso de UTF-8 válido, pero no filtran casi ninguno de los caracteres UTF-8 incorrectos de mis datos de prueba: capacidad del decodificador UTF-8 y prueba de esfuerzo . O bien los caracteres malos no se modifican o parece que se eliminan algunos de sus bytes, lo que crea un nuevo carácter no válido.
No estoy muy familiarizado con el estándar UTF-8 o con multibyte en JavaScript, por lo que no estoy seguro de si no estoy representando el UTF-8 adecuado en la expresión regular o si estoy aplicando la expresión regular de manera incorrecta en JavaScript.
Edición: agregue una marca global a mi expresión regular por el comentario de Tomalak, sin embargo, esto todavía no funciona para mí. Estoy abandonando hacer esto en el lado del cliente por el comentario de Bobince.
Las cadenas de JavaScript son nativamente Unicode. Contienen secuencias de caracteres * no secuencias de bytes, por lo que es imposible que una contenga una secuencia de bytes no válida.
(Técnicamente, en realidad contienen secuencias de unidades de código UTF-16, que no es exactamente lo mismo, pero probablemente no sea algo de lo que deba preocuparse en este momento).
Puede, si lo necesita, por alguna razón, crear una cadena que contenga los caracteres utilizados como marcadores de posición para los bytes. es decir. utilizando el carácter U+0080
(''/ x80'') para representar el byte 0x80. Esto es lo que obtendría si codificara caracteres a bytes usando UTF-8, y luego los decodificara a caracteres usando ISO-8859-1 por error. Hay un lenguaje especial de JavaScript para esto:
var bytelike= unescape(encodeURIComponent(characters));
y para volver de los pseudobytes a caracteres UTF-8 nuevamente:
var characters= decodeURIComponent(escape(bytelike));
(Esto es, notablemente, prácticamente la única vez que se deberían usar las funciones unescape
/ unescape
. Su existencia en cualquier otro programa es casi siempre un error).
decodeURIComponent(escape(bytes))
, ya que se comporta como un decodificador UTF-8, generará un error si la secuencia de unidades de código que se alimenta no sería aceptable como UTF-8 bytes.
Es muy raro que necesite trabajar con cadenas de bytes como esta en JavaScript. Mejor seguir trabajando de forma nativa en Unicode en el lado del cliente. El navegador se encargará de la codificación UTF-8 de la cadena en el cable (en un envío de formulario o XMLHttpRequest).
Me encontré con este problema con un resultado realmente extraño de los datos de fecha de toma de una imagen digital. Mi escenario es ciertamente único: utiliza el host de scripting de Windows (wsh) y el objeto Activex de Shell.Application que permite obtener el objeto de espacio de nombres de una carpeta y llamar a la función GetDetailsOf para que esencialmente devuelva datos exif después de que el SO los haya analizado.
var app = new ActiveXObject("Shell.Application");
var info = app.Namespace("c:/");
var date = info.GetDetailsOf(info.ParseName("testimg.jpg"), 12);
En Windws Vista y 7, el resultado se veía así:
?8/?27/?2011 ??11:45 PM
Así que mi enfoque fue el siguiente:
var chars = date.split(''''); //split into characters
var clean = "";
for (var i = 0; i < chars.length; i++) {
if (chars[i].charCodeAt(0) < 255) clean += chars[i];
}
El resultado, por supuesto, es una cadena que excluye esos caracteres de signo de interrogación.
Sé que optó por una solución diferente, pero pensé que publicaría mi solución en caso de que alguien más tenga problemas con esto y no pueda utilizar un enfoque de lenguaje del lado del servidor.
Si está intentando eliminar el "carácter no válido" - - de las cadenas de javascript, entonces puede deshacerse de ellos de esta manera:
myString = myString.replace(//uFFFD/g, '''')
Yo uso este enfoque simple y robusto:
function cleanString(input) {
var output = "";
for (var i=0; i<input.length; i++) {
if (input.charCodeAt(i) <= 127) {
output += input.charAt(i);
}
}
return output;
}
Básicamente, todo lo que realmente quieres son los caracteres ASCII 0-127, así que simplemente reconstruye la cadena char por char. Si es un buen personaje, consérvelo; si no, córtalo. Bastante robusto y si el objetivo es el saneamiento, es lo suficientemente rápido (de hecho, es muy rápido).