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

时间:2011-10-25 05:36:39

标签: javascript decode urldecode

我不确定这是什么,所以我在搜索时遇到了麻烦。如何使用JavaScript从http\u00253A\u00252F\u00252Fexample.comhttp://example.com解码带有unicode的字符串?我尝试了unescapedecodeURIdecodeURIComponent,所以我想剩下的就是字符串替换。

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

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

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

7 个答案:

答案 0 :(得分:102)

更新:请注意,这是一个适用于旧浏览器或非浏览器平台的解决方案,并且为了教学目的而保持活跃。请参阅下面的@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

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

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

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

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

答案 1 :(得分:87)

原始答案:

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

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

编辑(2017-10-12)

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

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

答案 2 :(得分:14)

请注意,unescape()的使用是deprecated,并且不适用于TypeScript编译器。

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

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

http://example.com

答案 3 :(得分:2)

查看此页面:http://www.rishida.net/tools/conversion/

将代码粘贴到顶部文本框中(首先删除双斜杠)。

代码是开源的:http://www.rishida.net/tools/conversion/conversionfunctions.js

答案 4 :(得分:2)

我没有足够的代表将其置于对现有答案的评论之下:

unescape仅用于处理URI(或任何编码的utf-8),这可能是大多数人的需求。 encodeURIComponent将js字符串转换为转义的UTF-8,而decodeURIComponent仅适用于转义的UTF-8字节。它会导致像decodeURIComponent('%a9'); // error这样的错误,因为扩展的ascii无效utf-8(即使它仍然是unicode值),而unescape('%a9'); // ©所以你需要在使用decodeURIComponent时知道你的数据。

decodeURIComponent不会对"%C2"0x7f上的任何单个字节起作用,因为在utf-8中表示代理的一部分。但decodeURIComponent("%C2%A9") //gives you © Unescape无法在// ©上正常工作,并且不会引发错误,因此如果您不知道自己的数据,unescape会导致错误的代码。

答案 5 :(得分:0)

为此使用JSON.decode会带来一些明显的缺点,您必须意识到:

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

还有其他注意事项。本质上,为此目的使用\\u{045}是一种黑客行为,并且无法以您一直期望的方式工作。您应该坚持使用JSON.decode库处理JSON,而不是字符串操作。


我最近自己遇到了这个问题,并想要一个强大的解码器,所以我最终自己写了一个。它是完整且经过全面测试的,可在以下位置找到:https://github.com/iansan5653/unraw。它尽可能地模仿JavaScript标准。

说明:

该源大约有250行,因此在这里我不会全部包括在内,但实际上,它使用以下正则表达式查找所有转义序列,然后使用JSON对其进行解析以解码以16为底的数字,然后parseInt(string, 16)获取相应的字符:

String.fromCodePoint(number)

注释(注意:此正则表达式与所有转义序列匹配,包括无效的转义序列。如果该字符串在JS中引发错误,则在我的库中引发错误[即/\\(?:(\\)|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 将出错)):

'\x!!'

示例

使用该库:

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

答案 6 :(得分:0)

就我而言,我正在尝试 unescape HTML 文件之类的

"\u003Cdiv id=\u0022app\u0022\u003E\r\n    \u003Cdiv data-v-269b6c0d\u003E\r\n        \u003Cdiv data-v-269b6c0d class=\u0022menu\u0022\u003E\r\n    \u003Cdiv data-v-269b6c0d class=\u0022faux_column\u0022\u003E\r\n        \u003Cdiv data-v-269b6c0d class=\u0022row\u0022\u003E\r\n            \u003Cdiv data-v-269b6c0d class=\u0022col-md-12\u0022\u003E\r\n"  

<div id="app">
    <div data-v-269b6c0d>
        <div data-v-269b6c0d class="menu">
    <div data-v-269b6c0d class="faux_column">
        <div data-v-269b6c0d class="row">
            <div data-v-269b6c0d class="col-md-12">

以下适用于我的情况:

const jsEscape = (str: string) => {
  return str.replace(new RegExp("'", 'g'),"\\'");
}

export const decodeUnicodeEntities = (data: any) => {
  return unescape(jsEscape(data));
}

// Use it
const data = ".....";
const unescaped = decodeUnicodeEntities(data); // Unescaped html