Je ne sais pas comment cela s'appelle, j'ai donc du mal à le rechercher. Comment puis-je 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 donc je suppose que la seule chose qui reste est le remplacement de chaîne.

EDIT: La chaîne n'est pas tapé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.

78
styfle 25 oct. 2011 à 09:36

5 réponses

Meilleure réponse

Réponse originale:

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

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

Modifier (2017-10-12) :

@MechaLynx et @ Kevin-Weber notent que unescape() est déconseillé aux environnements sans navigateur et n'existe pas dans TypeScript. decodeURIComponent est un remplacement sans rendez-vous. Pour une compatibilité plus large, utilisez plutôt ce qui suit:

decodeURIComponent(JSON.parse('"http\\u00253A\\u00252F\\u00252Fexample.com"'));
> 'http://example.com'
97
radicand 12 oct. 2017 à 20:57

Je n'ai pas assez de représentant pour mettre ceci sous les commentaires aux réponses existantes:

unescape est uniquement déconseillé pour travailler avec des URI (ou tout utf-8 codé), ce qui est probablement le cas pour la plupart des besoins des gens. encodeURIComponent convertit une chaîne js en UTF-8 d'échappement et decodeURIComponent ne fonctionne que sur les octets UTF-8 d'échappement. Il génère une erreur pour quelque chose comme decodeURIComponent('%a9'); // error parce que l'ascii étendu n'est pas valide utf-8 (même si c'est toujours une valeur unicode), tandis que unescape('%a9'); // © Vous devez donc connaître vos données lorsque vous utilisez decodeURIComponent.

DecodeURIComponent ne fonctionnera pas sur "%C2" ou tout octet isolé sur 0x7f car dans utf-8 qui indique une partie d'un substitut. Cependant, decodeURIComponent("%C2%A9") //gives you © Unescape ne fonctionnerait pas correctement sur ce // © ET cela ne générerait pas d'erreur, donc unescape peut conduire à du code bogué si vous ne connaissez pas vos données.

2
aamarks 15 mars 2018 à 22:21

Notez que l'utilisation de unescape() est déconseillée et ne fonctionne pas avec le compilateur TypeScript, par exemple.

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

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

http://example.com

20
Kevin Weber 3 nov. 2016 à 20:43

MISE À JOUR : veuillez noter qu'il s'agit d'une solution qui devrait s'appliquer aux navigateurs plus anciens ou aux plates-formes sans navigateur, et qui est maintenue en vie à des fins pédagogiques. Veuillez vous référer à la réponse de @radicand ci-dessous pour une réponse plus à jour.


Il s'agit d'une chaîne d'échappement unicode. La chaîne a d'abord été échappée, puis encodé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 instances de la chaîne, pas seulement la première, et que la correspondance doit être insensible à la casse. Cela peut sembler inutile compte tenu de l'exemple, mais cela ajoute de la polyvalence.

Maintenant, pour convertir d'une chaîne à la suivante, je dois exécuter certaines étapes sur chaque groupe de chaque correspondance, et je ne peux pas le faire en transformant simplement la chaîne. Utilement, 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 j'ai besoin d'utiliser, et le transforme en la séquence utf-8 équivalente, puis j'utilise la fonction intégrée unescape pour décoder la chaîne dans sa forme appropriée.

112
Ioannis Karadimas 22 févr. 2018 à 08:03

L'utilisation de JSON.decode à cet effet présente des inconvénients importants dont vous devez être conscient:

  • Vous devez mettre la chaîne entre guillemets doubles
  • De nombreux caractères ne sont pas pris en charge et doivent être échappés eux-mêmes. Par exemple, la transmission de l'un des éléments suivants à JSON.decode (après les avoir placés entre guillemets doubles) entraînera une erreur, même s'ils sont tous valides: \\n, \n, \\0, { {X4}}
  • Il ne prend pas en charge les échappements hexadécimaux: \\x45
  • Il ne prend pas en charge les séquences de points de code Unicode: \\u{045}

Il y a également d'autres mises en garde. Essentiellement, l'utilisation de JSON.decode à cette fin est un hack et ne fonctionne pas comme vous pouvez toujours vous y attendre. Vous devez vous en tenir à l'utilisation de la bibliothèque JSON pour gérer JSON, pas pour les opérations de chaîne.


J'ai récemment rencontré ce problème moi-même et je voulais un décodeur robuste, donc j'ai fini par en écrire un moi-même. Il est complet et minutieusement testé et est disponible ici: https://github.com/iansan5653/unraw. Il imite le standard JavaScript aussi étroitement que possible.

Explication:

La source est d'environ 250 lignes, donc je ne vais 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 {{X1 }} 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é (REMARQUE: cette expression régulière correspond à toutes les séquences d'échappement, y compris les séquences non valides. Si la chaîne génère une erreur dans JS, elle renvoie une erreur dans ma bibliothèque [c'est-à-dire que '\x!!' commettra 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

Utilisation de 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 19 août 2019 à 16:37
7885096