[javascript] 이스케이프 된 유니 코드로 문자열을 어떻게 디코딩합니까?

이름이 무엇인지 잘 모르기 때문에 검색하는 데 문제가 있습니다. 어떻게에서 유니 코드 문자열을 디코딩 할 수 http\u00253A\u00252F\u00252Fexample.comhttp://example.com자바 스크립트로? 나는 노력 unescape, decodeURI그리고 decodeURIComponent그래서 남은 건 오직 문자열 교체 것 같다.

편집 : 문자열이 입력되지 않고 다른 코드의 부분 문자열입니다. 따라서 문제를 해결하려면 다음과 같이 시작해야합니다.

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

이것이 unescape ()가 작동하지 않는 이유를 보여주기를 바랍니다.



답변

수정 (2017-10-12) :

@MechaLynx 및 @ Kevin-Weber unescape()는 브라우저가 아닌 환경에서 더 이상 사용되지 않으며 TypeScript에 존재하지 않습니다. decodeURIComponent드롭 인 교체입니다. 더 광범위한 호환성을 위해 대신 아래를 사용하십시오.

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

원래 답변 :

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

모든 작업을 JSON.parse


답변

업데이트 : 이것은 이전 브라우저 또는 비 브라우저 플랫폼에 적용해야하는 솔루션이며 교육 목적으로 유지됩니다. 최신 답변은 아래 @radicand의 답변을 참조하십시오.


이것은 유니 코드, 이스케이프 된 문자열입니다. 먼저 문자열이 이스케이프 된 다음 유니 코드로 인코딩되었습니다. 다시 정상으로 변환하려면 :

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함수를 사용하여 문자열을 적절한 형식으로 디코딩합니다.


답변

예를 들어 의 사용 unescape()더 이상 사용되지 않으며 TypeScript 컴파일러에서는 작동하지 않습니다.

radicand의 답변과 아래 댓글 섹션을 기반으로 업데이트 된 솔루션은 다음과 같습니다.

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

http://example.com


답변

나는 이것을 기존 답변에 대한 주석 아래에 넣을 충분한 담당자가 없습니다.

unescape대부분의 사람들의 요구에 해당하는 URI (또는 인코딩 된 utf-8) 작업에만 사용되지 않습니다. encodeURIComponentjs 문자열을 이스케이프 된 UTF-8로 변환하고 decodeURIComponent이스케이프 된 UTF-8 바이트에서만 작동합니다. decodeURIComponent('%a9'); // error확장 ASCII가 유효한 utf-8이 아니기 때문에 오류가 발생합니다 (아직 유니 코드 값 임에도 불구하고).unescape('%a9'); // © decodeURIComponent를 사용할 때 데이터를 알아야합니다.

decodeURIComponent는 대리자의 일부를 나타내는 utf-8에서 작동 하기 때문에 "%C2"또는 어떤 외로운 바이트 에서 작동하지 않습니다 0x7f. 그러나 decodeURIComponent("%C2%A9") //gives you ©Unescape는 제대로 작동하지 // ©않으며 오류가 발생하지 않으므로 데이터를 모르는 경우 unescape는 버그가있는 코드로 이어질 수 있습니다.


답변

이를 JSON.decode위해 사용하면 알아야 할 중요한 단점이 있습니다.

  • 문자열을 큰 따옴표로 묶어야합니다.
  • 많은 문자가 지원되지 않으며 스스로 이스케이프해야합니다. 예를 들어,에 다음 중 하나를 통과 JSON.decode(따옴표에 그들을 배치 후 것은)이 모두 유효하더라도 오류가 발생하지 : \\n, \n, \\0,a"a
  • 16 진수 이스케이프를 지원하지 않습니다. \\x45
  • 유니 코드 코드 포인트 시퀀스를 지원하지 않습니다. \\u{045}

다른주의 사항도 있습니다. 기본적 JSON.decode으로 이러한 목적으로 사용하는 것은 해킹이며 항상 예상하는 방식으로 작동하지 않습니다. JSON문자열 작업이 아니라 라이브러리를 사용하여 JSON을 처리 해야 합니다.


나는 최근에이 문제를 직접 겪었고 강력한 디코더를 원했기 때문에 결국 직접 작성했습니다. 완전하고 철저하게 테스트되었으며 여기에서 사용할 수 있습니다 : https://github.com/iansan5653/unraw . 가능한 한 JavaScript 표준을 모방합니다.

설명:

소스는 약 250 줄이므로 여기에 모두 포함하지는 않지만 기본적으로 다음 Regex를 사용하여 모든 이스케이프 시퀀스를 찾은 다음 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

주석 처리됨 (참고 :이 정규식은 유효하지 않은 것을 포함하여 모든 이스케이프 시퀀스와 일치합니다. 문자열이 JS에서 오류를 발생 시키면 내 라이브러리에 '\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

해당 라이브러리 사용 :

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


답변