web-dev-qa-db-fra.com

Comment décoder une chaîne avec unicode échappé?

Je ne sais pas comment ça s'appelle alors j'ai du mal à le chercher. Comment décoder une chaîne avec unicode de http\u00253A\u00252F\u00252Fexample.com à http://example.com avec JavaScript? J'ai essayé unescape, decodeURI et decodeURIComponent alors je suppose que la seule chose qui reste à faire est de remplacer la chaîne.

EDIT: La chaîne n'est pas typée, mais plutôt une sous-chaîne d'un autre morceau de code. Donc, pour résoudre le problème, vous devez commencer par quelque chose comme ceci:

var s = 'http\\u00253A\\u00252F\\u00252Fexample.com';

J'espère que cela montre pourquoi unescape () ne fonctionne pas.

74
styfle

Réponse originale:

unescape(JSON.parse('"http\\u00253A\\u00252F\\u00252Fexample.com"'));
> 'http://example.com'

Vous pouvez décharger tout le travail sur JSON.parse

Edit (2017-10-12):

@MechaLynx et @ Kevin-Weber notent que unescape() est déconseillé dans les environnements autres que les navigateurs et n'existe pas dans TypeScript. decodeURIComponent est un remplacement instantané. Pour une compatibilité plus large, utilisez plutôt le code ci-dessous:

decodeURIComponent(JSON.parse('"http\\u00253A\\u00252F\\u00252Fexample.com"'));
> 'http://example.com'
89
radicand

UPDATE : notez qu'il s'agit d'une solution qui devrait s'appliquer aux navigateurs plus anciens ou à des plates-formes autres que des navigateurs et qui est maintenue en vie à des fins pédagogiques. Veuillez vous reporter à la réponse de @radicand ci-dessous pour une réponse plus à jour.


Ceci est une chaîne échappée unicode. La chaîne a d'abord été échappée, puis codée avec unicode. Pour revenir à la normale:

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

Pour expliquer: j'utilise une expression régulière pour rechercher \u0025. Cependant, comme je n’ai besoin que d’une partie de cette chaîne pour mon opération de remplacement, j’utilise des parenthèses pour isoler la partie que je vais réutiliser, 0025. Cette partie isolée s'appelle un groupe.

La partie gi à la fin de l'expression indique qu'elle doit correspondre à toutes les occurrences de la chaîne, et pas seulement à la première, et que la correspondance ne doit pas être sensible à la casse. Cela peut sembler inutile compte tenu de l'exemple, mais cela ajoute à la polyvalence.

Maintenant, pour convertir une chaîne en chaîne, je dois exécuter quelques étapes sur chaque groupe de chaque correspondance, et je ne peux pas le faire en transformant simplement la chaîne. De manière utile, l'opération String.replace peut accepter une fonction qui sera exécutée pour chaque correspondance. Le retour de cette fonction remplacera la correspondance elle-même dans la chaîne.

J'utilise le deuxième paramètre que cette fonction accepte, qui est le groupe que je dois utiliser, et le transforme en séquence équivalente à utf-8, puis utilise la fonction intégrée unescape pour décoder la chaîne dans sa forme appropriée .

105
Ioannis Karadimas

Notez que l'utilisation de unescape() est obsolète et ne fonctionne pas avec le compilateur TypeScript, par exemple.

Sur la base de la réponse de radicand et de la section commentaires ci-dessous, voici une solution mise à jour:

var string = "http\\u00253A\\u00252F\\u00252Fexample.com";
decodeURIComponent(JSON.parse('"' + string.replace(/\"/g, '\\"') + '"'));

http://example.com

15
Kevin Weber

Je n'ai pas assez de représentants pour mettre cela sous les commentaires des réponses existantes:

unescape est seulement déconseillé pour travailler avec des URI (ou n'importe quel utf-8 codé), ce qui est probablement le cas pour les besoins de la plupart des gens. encodeURIComponent convertit une chaîne js en UTF-8 échappé et decodeURIComponent ne fonctionne que sur les octets UTF-8 échappés. Il renvoie une erreur pour quelque chose comme decodeURIComponent('%a9'); // error parce que l'ASCII étendu n'est pas valide en utf-8 (même s'il s'agit toujours d'une valeur unicode), alors que unescape('%a9'); // © vous devez donc connaître vos données lorsque en utilisant decodeURIComponent.

decodeURIComponent ne fonctionnera pas avec "%C2" ou avec un seul octet dépassant 0x7f car utf-8 indique une partie d'un substitut. Cependant decodeURIComponent("%C2%A9") //gives you © Unescape ne fonctionnerait pas correctement sur ce // © ET cela ne déclencherait pas d'erreur. Unescape peut donc conduire à un code erroné si vous ne connaissez pas vos données.

2
aamarks

Regardez cette page: http://www.rishida.net/tools/conversion/

Collez votre code dans la zone de texte supérieure (supprimez d’abord les doubles barres obliques).

Le code est open source: http://www.rishida.net/tools/conversion/conversionfunctions.js

2
Petah

L'utilisation de JSON.decode Pour cela comporte des inconvénients importants que vous devez connaître:

  • Vous devez envelopper la chaîne entre guillemets
  • Beaucoup de caractères ne sont pas supportés et doivent être échappés. Par exemple, passer l'un des éléments suivants à JSON.decode (Après les avoir mis entre guillemets) entraînera une erreur même si elles sont toutes valides: \\n, \n, \\0, a"a
  • Il ne supporte pas les échappements hexadécimaux: \\x45
  • Il ne prend pas en charge les séquences de points de code Unicode: \\u{045}

Il y a aussi d'autres mises en garde. Utiliser essentiellement JSON.decode À cette fin est un hack et ne fonctionne pas comme prévu. Vous devriez vous en tenir à utiliser la bibliothèque JSON pour gérer JSON, et non pour les opérations sur les chaînes.


J'ai récemment rencontré ce problème moi-même et je voulais un décodeur robuste. J'en ai donc écrit un moi-même. C'est complet et complètement testé et est disponible ici: https://github.com/iansan5653/unraw . Il imite le standard JavaScript aussi fidèlement que possible.

Explication:

La source contient environ 250 lignes, je ne vais donc pas tout inclure ici, mais essentiellement, elle utilise la regex suivante pour trouver toutes les séquences d'échappement, puis les analyse en utilisant parseInt(string, 16) pour décoder les nombres en base 16, puis String.fromCodePoint(number) pour obtenir le caractère correspondant:

/\\(?:(\\)|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

Commenté (NOTE: Cette expression rationnelle correspond à toutes les séquences d'échappement, y compris celles qui ne sont pas valides. Si la chaîne génère une erreur dans JS, elle génère une erreur dans ma bibliothèque [c'est-à-dire, '\x!!' Sera une erreur]):

/
\\ # 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

Exemple

Utiliser cette bibliothèque:

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
0
Ian