如何使用转义的unicode解码字符串?

sty*_*fle 75 javascript decode urldecode

我不确定这叫什么,所以我很难找到它.如何从解码使用Unicode字符串http\u00253A\u00252F\u00252Fexample.comhttp://example.com使用JavaScript?我想unescape,decodeURIdecodeURIComponent所以我想留下的唯一的事情是字符串替换.

编辑:字符串不是键入的,而是来自另一段代码的子字符串.所以要解决这个问题,你必须从这样的事情开始:

var s = 'http\\u00253A\\u00252F\\u00252Fexample.com';
Run Code Online (Sandbox Code Playgroud)

我希望这表明为什么unescape()不起作用.

Ioa*_*mas 109

更新:请注意,这是一个适用于旧浏览器或非浏览器平台的解决方案,并且为了教学目的而保持活跃.有关更新的答案,请参阅下面的@radicand的答案.


这是一个unicode,转义字符串.首先对字符串进行转义,然后使用unicode进行编码.要转换回正常:

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
Run Code Online (Sandbox Code Playgroud)

解释:我使用正则表达式来寻找\u0025.但是,由于我只需要将此字符串的一部分用于替换操作,因此我使用括号来隔离我将要重用的部分0025.这个孤立的部分称为一个组.

gi表达式末尾的部分表示它应该匹配字符串中的所有实例,而不仅仅是第一个实例,并且匹配应该不区分大小写.考虑到这个例子,这可能看起来不必要,但它增加了多功能性.

现在,要从一个字符串转换到下一个字符串,我需要在每个匹配的每个组上执行一些步骤,我不能通过简单地转换字符串来做到这一点.有用的是,String.replace操作可以接受一个函数,该函数将为每个匹配执行.该函数的返回将替换字符串中的匹配本身.

我使用此函数接受的第二个参数,即我需要使用的组,并将其转换为等效的utf-8序列,然后使用内置unescape函数将字符串解码为其正确的形式.

  • 谢谢.你能解释一下你在做什么吗?看起来正则表达式正在寻找一个`\ u`前缀而不是一个4字符的十六进制数字(字母或数字).replace方法中的函数如何工作? (3认同)
  • 请注意,这似乎比`JSON.parse`方法慢得多:http://jsperf.com/unicode-func-vs-json-parse (2认同)

rad*_*and 91

原始答案:

unescape(JSON.parse('"http\\u00253A\\u00252F\\u00252Fexample.com"'));
> 'http://example.com'
Run Code Online (Sandbox Code Playgroud)

你可以将所有工作卸载到 JSON.parse

编辑(2017-10-12):

@MechaLynx和@ Kevin-Weber注释unescape()在非浏览器环境中已弃用,在TypeScript中不存在.decodeURIComponent是一个替代品.为了更广泛的兼容性,请使用以下代码:

decodeURIComponent(JSON.parse('"http\\u00253A\\u00252F\\u00252Fexample.com"'));
> 'http://example.com'
Run Code Online (Sandbox Code Playgroud)

  • 关于@ styfle答案的重要说明:处理不受信任的数据时,不要使用`JSON.parse('"'+ s +'"')``JSON.parse('"'+ s.replace('"', '\\'''+'"')`而不是,当输入包含引号时,你的代码*将会中断*. (17认同)
  • 很棒的答案@ alexander255,但你实际上想要使用:JSON.parse('"'+ str.replace(/ \"/ g,'\\"'+'"')替换整个字符中出现的所有字符字符串,而不是替换一个. (7认同)
  • 有趣.我不得不在它周围添加引号`unescape(JSON.parse('"'+ s +'"'));`额外报价的原因是什么?这会使它成为有效的JSON吗? (5认同)
  • 对于那些遇到这个并且因为`unescape()`已经被弃用而感到担心的人来说,`decodeURIComponent()`在这种情况下与`unescape()`完全相同,所以只需用它替换它就可以了. (2认同)

Kev*_*ber 17

请注意,使用的unescape()过时和不与打字稿编译工作,例如.

根据radicand的答案和下面的评论部分,这是一个更新的解决方案:

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

http://example.com


Ian*_*Ian 10

使用JSON.decode此方法会带来您必须注意的重大缺点:

  • 您必须将字符串括在双引号中
  • 许多字符不受支持,必须自行转义。例如,将以下任何内容传递给JSON.decode(用双引号括起来之后)都会出错,即使这些内容都是有效的:\\n, \n, \\0,a"a
  • 它不支持十六进制转义:\\x45
  • 它不支持 Unicode 代码点序列:\\u{045}

还有其他注意事项。本质上,用于JSON.decode此目的是一种黑客行为,并且不会按照您期望的方式工作。您应该坚持使用该JSON库来处理 JSON,而不是字符串操作。


我最近自己遇到了这个问题,想要一个强大的解码器,所以我最终自己写了一个。它经过完整且彻底的测试,可在此处获取: https: //github.com/iansan5653/unraw。它尽可能地模仿 JavaScript 标准。

解释:

源代码大约有 250 行,所以我不会将其全部包含在这里,但本质上它使用以下正则表达式来查找所有转义序列,然后使用解码parseInt(string, 16)基 16 数字来解析它们,然后String.fromCodePoint(number)获取相应的字符:

/\\(?:(\\)|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
Run Code Online (Sandbox Code Playgroud)

注释(注意:这个正则表达式匹配所有转义序列,包括无效的序列。如果该字符串在 JS 中抛出错误,它也会在我的库中抛出错误 [即,'\x!!'将出错]):

/\\(?:(\\)|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
Run Code Online (Sandbox Code Playgroud)

例子

使用该库:

/
\\ # 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
Run Code Online (Sandbox Code Playgroud)