No estoy seguro de cómo se llama, así que tengo problemas para buscarlo. ¿Cómo puedo decodificar una cadena con unicode de http\u00253A\u00252F\u00252Fexample.com
a http://example.com
con JavaScript? Lo intenté unescape
, decodeURI
y decodeURIComponent
supongo que lo único que queda es reemplazar la cadena.
EDITAR: La cadena no se escribe, sino una subcadena de otra pieza de código. Entonces, para resolver el problema, debes comenzar con algo como esto:
var s = 'http\\u00253A\\u00252F\\u00252Fexample.com';
Espero que eso demuestre por qué unescape () no funciona.
javascript
decode
urldecode
styfle
fuente
fuente
Respuestas:
Editar (12/10/2017) :
@MechaLynx y @ Kevin-Weber notan que
unescape()
está obsoleto en entornos que no son de navegador y no existe en TypeScript.decodeURIComponent
es un reemplazo directo. Para una compatibilidad más amplia, use lo siguiente en su lugar:decodeURIComponent(JSON.parse('"http\\u00253A\\u00252F\\u00252Fexample.com"')); > 'http://example.com'
Respuesta original:
unescape(JSON.parse('"http\\u00253A\\u00252F\\u00252Fexample.com"')); > 'http://example.com'
Puedes descargar todo el trabajo a
JSON.parse
fuente
unescape(JSON.parse('"' + s + '"'));
¿Cuál es el motivo de las comillas adicionales? ¿Eso lo convierte en JSON válido?fromCharCode
enfoque: jsperf.com/unicode-func-vs-json-parseJSON.parse('"' + s + '"')
cuando se trate de datos no confiablesJSON.parse('"' + s.replace('"', '\\"') + '"')
, de lo contrario, su código se romperá cuando la entrada contenga comillas.unescape()
se ha desaprobado,decodeURIComponent()
funciona de manera idénticaunescape()
en este caso, así que simplemente reemplácelo con eso y estará bien.ACTUALIZACIÓN : tenga en cuenta que esta es una solución que debe aplicarse a navegadores más antiguos o plataformas que no son navegadores, y se mantiene activa con fines educativos. Consulte la respuesta de @radicand a continuación para obtener una respuesta más actualizada.
Esta es una cadena de escape Unicode. Primero se escapó la cadena, luego se codificó con Unicode. Para volver a la normalidad:
var x = "http\\u00253A\\u00252F\\u00252Fexample.com"; var r = /\\u([\d\w]{4})/gi; x = x.replace(r, function (match, grp) { return String.fromCharCode(parseInt(grp, 16)); } ); console.log(x); // http%3A%2F%2Fexample.com x = unescape(x); console.log(x); // http://example.com
Para explicar: utilizo una expresión regular para buscar
\u0025
. Sin embargo, ya que necesito sólo una parte de esta cadena para mi operación de reemplazo, uso de paréntesis para aislar la parte que voy a reutilización,0025
. Esta parte aislada se llama grupo.La
gi
parte al final de la expresión indica que debe coincidir con todas las instancias de la cadena, no solo con la primera, y que la coincidencia no debe distinguir entre mayúsculas y minúsculas. Esto puede parecer innecesario dado el ejemplo, pero agrega versatilidad.Ahora, para convertir de una cadena a la siguiente, necesito ejecutar algunos pasos en cada grupo de cada coincidencia, y no puedo hacerlo simplemente transformando la cadena. Afortunadamente, la operación String.replace puede aceptar una función, que se ejecutará para cada coincidencia. El retorno de esa función reemplazará la coincidencia en la cadena.
Utilizo el segundo parámetro que acepta esta función, que es el grupo que necesito usar, y lo transformo a la secuencia utf-8 equivalente, luego uso la
unescape
función incorporada para decodificar la cadena a su forma adecuada.fuente
\u
prefijo y un número hexadecimal de 4 caracteres (letras o números). ¿Cómo funciona la función en el método de reemplazo?var r = /\\u([\d\w]{1,})/gi;
JSON.parse
enfoque: jsperf.com/unicode-func-vs-json-parseunescape()
puede usarlodecodeURIComponent()
. Funciona de forma idéntica en este caso. Sin embargo, recomendaría el enfoque de radicand, ya que es más simple, igual de compatible y más rápido de ejecutar, con los mismos resultados (asegúrese de leer los comentarios sin embargo).Tenga en cuenta que el uso de
unescape()
está obsoleto y no funciona con el compilador de TypeScript, por ejemplo.Según la respuesta de radicand y la sección de comentarios a continuación, aquí hay una solución actualizada:
var string = "http\\u00253A\\u00252F\\u00252Fexample.com"; decodeURIComponent(JSON.parse('"' + string.replace(/\"/g, '\\"') + '"'));
http://example.com
fuente
No tengo suficiente representante para poner esto en comentarios a las respuestas existentes:
unescape
solo está en desuso para trabajar con URI (o cualquier utf-8 codificado) que es probablemente el caso para las necesidades de la mayoría de las personas.encodeURIComponent
convierte una cadena js en UTF-8 de escape ydecodeURIComponent
solo funciona en bytes UTF-8 de escape. Lanza un error para algo comodecodeURIComponent('%a9'); // error
porque ascii extendido no es utf-8 válido (aunque sigue siendo un valor unicode), mientras que,unescape('%a9'); // ©
por lo tanto, necesita conocer sus datos cuando use decodeURIComponent.decodeURIComponent no funcionará en
"%C2"
ningún byte solitario0x7f
porque en utf-8 eso indica parte de un sustituto. Sin embargo,decodeURIComponent("%C2%A9") //gives you ©
Unescape no funcionaría correctamente en eso// ©
Y no arrojaría un error, por lo que unescape puede generar un código defectuoso si no conoce sus datos.fuente
El uso
JSON.decode
para esto conlleva importantes inconvenientes que debe tener en cuenta:JSON.decode
(después de concluir entre comillas dobles) será de error aunque éstas son todas válidas:\\n
,\n
,\\0
,a"a
\\x45
\\u{045}
También hay otras advertencias. Esencialmente, usarlo
JSON.decode
para este propósito es un truco y no funciona de la manera que siempre podría esperar. Debe seguir usando laJSON
biblioteca para manejar JSON, no para operaciones de cadena.Recientemente me encontré con este problema y quería un decodificador robusto, así que terminé escribiendo uno yo mismo. Está completo y probado a fondo y está disponible aquí: https://github.com/iansan5653/unraw . Imita el estándar JavaScript lo más fielmente posible.
Explicación:
La fuente es de aproximadamente 250 líneas, por lo que no lo incluiré todo aquí, pero esencialmente usa la siguiente expresión regular para encontrar todas las secuencias de escape y luego las analiza
parseInt(string, 16)
para decodificar los números en base 16 y luegoString.fromCodePoint(number)
para obtener el carácter correspondiente:/\\(?:(\\)|x([\s\S]{0,2})|u(\{[^}]*\}?)|u([\s\S]{4})\\u([^{][\s\S]{0,3})|u([\s\S]{0,4})|([0-3]?[0-7]{1,2})|([\s\S])|$)/g
Comentado (NOTA: Esta expresión regular coincide con todas las secuencias de escape, incluidas las no válidas. Si la cadena arrojaría un error en JS, arrojaría un error en mi biblioteca [es decir,
'\x!!'
generará un error]):/ \\ # All escape sequences start with a backslash (?: # Starts a group of 'or' statements (\\) # If a second backslash is encountered, stop there (it's an escaped slash) | # or x([\s\S]{0,2}) # Match valid hexadecimal sequences | # or u(\{[^}]*\}?) # Match valid code point sequences | # or u([\s\S]{4})\\u([^{][\s\S]{0,3}) # Match surrogate code points which get parsed together | # or u([\s\S]{0,4}) # Match non-surrogate Unicode sequences | # or ([0-3]?[0-7]{1,2}) # Match deprecated octal sequences | # or ([\s\S]) # Match anything else ('.' doesn't match newlines) | # or $ # Match the end of the string ) # End the group of 'or' statements /g # Match as many instances as there are
Ejemplo
Usando esa biblioteca:
import unraw from "unraw"; let step1 = unraw('http\\u00253A\\u00252F\\u00252Fexample.com'); // yields "http%3A%2F%2Fexample.com" // Then you can use decodeURIComponent to further decode it: let step2 = decodeURIComponent(step1); // yields http://example.com
fuente