Nie jestem pewien, jak to się nazywa, więc mam problemy z jego wyszukaniem. Jak zdekodować ciąg znaków Unicode od http\u00253A\u00252F\u00252Fexample.com
do za http://example.com
pomocą JavaScript? Próbowałem unescape
, decodeURI
i decodeURIComponent
tak myślę, że jedyną rzeczą, w lewo jest ciąg zastąpić.
EDYCJA: Ciąg nie jest wpisywany, ale podciąg z innego fragmentu kodu. Aby rozwiązać problem, musisz zacząć od czegoś takiego:
var s = 'http\\u00253A\\u00252F\\u00252Fexample.com';
Mam nadzieję, że to pokazuje, dlaczego unescape () nie działa.
javascript
decode
urldecode
styfle
źródło
źródło
Odpowiedzi:
Edycja (2017-10-12) :
@MechaLynx i @ Kevin-Weber uwaga, która
unescape()
jest przestarzała ze środowisk innych niż przeglądarki i nie istnieje w TypeScript.decodeURIComponent
jest zamiennikiem typu drop-in. Aby uzyskać szerszą zgodność, użyj zamiast tego poniższego:decodeURIComponent(JSON.parse('"http\\u00253A\\u00252F\\u00252Fexample.com"')); > 'http://example.com'
Oryginalna odpowiedź:
unescape(JSON.parse('"http\\u00253A\\u00252F\\u00252Fexample.com"')); > 'http://example.com'
Możesz odciążyć całą pracę
JSON.parse
źródło
unescape(JSON.parse('"' + s + '"'));
Jaki jest powód tych dodatkowych cytatów? Czy to czyni go poprawnym JSON?fromCharCode
podejście: jsperf.com/unicode-func-vs-json-parseJSON.parse('"' + s + '"')
czynienia z niezaufanymi danymiJSON.parse('"' + s.replace('"', '\\"') + '"')
, w przeciwnym razie twój kod zostanie uszkodzony, gdy dane wejściowe będą zawierały cudzysłowy.unescape()
został wycofany,decodeURIComponent()
działa identycznie jakunescape()
w tym przypadku, więc po prostu zastąp go tym i jesteś dobry.AKTUALIZACJA : Należy pamiętać, że jest to rozwiązanie, które powinno mieć zastosowanie do starszych przeglądarek lub platform innych niż przeglądarki i jest utrzymywane przy życiu do celów instruktażowych. Aby uzyskać bardziej aktualną odpowiedź, zapoznaj się z poniższą odpowiedzią @radicand.
To jest ciąg znaków ze znakami ucieczki Unicode. Najpierw ciąg został usunięty, a następnie zakodowany za pomocą Unicode. Aby przywrócić normalny tryb:
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
Aby wyjaśnić: szukam wyrażenia regularnego
\u0025
. Jednakże, ponieważ muszę tylko część tego łańcucha dla mojego zastąpienia pracy używam nawiasów wyizolować część Idę do ponownego wykorzystania0025
. Ta wyodrębniona część nazywana jest grupą.gi
Część na końcu wyrazu oznacza powinien dopasować wszystkie instancje w ciągu, nie tylko pierwszy, i że dopasowanie powinno być przypadek niewrażliwe. Na przykładzie może to wyglądać niepotrzebnie, ale zwiększa wszechstronność.Teraz, aby dokonać konwersji z jednego ciągu na drugi, muszę wykonać kilka kroków na każdej grupie każdego dopasowania, a nie mogę tego zrobić, po prostu przekształcając ciąg. Pomocne jest to, że operacja String.replace może przyjąć funkcję, która zostanie wykonana dla każdego dopasowania. Zwrócenie tej funkcji spowoduje zastąpienie samego dopasowania w ciągu.
Używam drugiego parametru, który akceptuje ta funkcja, czyli grupy, której potrzebuję, i przekształcam ją na równoważną sekwencję utf-8, a następnie używam wbudowanej
unescape
funkcji do dekodowania ciągu do jego właściwej postaci.źródło
\u
prefiksu, a następnie 4-znakowej liczby szesnastkowej (litery lub cyfry). Jak działa funkcja w metodzie replace?var r = /\\u([\d\w]{1,})/gi;
JSON.parse
podejście: jsperf.com/unicode-func-vs-json-parseunescape()
możedecodeURIComponent()
zamiast tego użyć . W tym przypadku działa identycznie. Poleciłbym jednak podejście radicand, ponieważ jest prostsze, tak samo obsługiwane i szybsze w wykonaniu, z tymi samymi wynikami (pamiętaj jednak o przeczytaniu komentarzy).Zauważ, że użycie
unescape()
jest przestarzałe i nie działa na przykład z kompilatorem TypeScript.Na podstawie odpowiedzi Radicand i sekcji komentarzy poniżej, oto zaktualizowane rozwiązanie:
var string = "http\\u00253A\\u00252F\\u00252Fexample.com"; decodeURIComponent(JSON.parse('"' + string.replace(/\"/g, '\\"') + '"'));
http://example.com
źródło
Nie mam wystarczającej liczby przedstawicieli, aby umieścić to pod komentarzami do istniejących odpowiedzi:
unescape
jest przestarzały tylko w przypadku pracy z identyfikatorami URI (lub jakimkolwiek zakodowanym utf-8), co prawdopodobnie ma miejsce w przypadku większości ludzi.encodeURIComponent
konwertuje ciąg znaków js na UTF-8 ze ucieczką idecodeURIComponent
działa tylko na bajtach UTF-8 ze ucieczką. Zgłasza błąd dla czegoś takiego jak,decodeURIComponent('%a9'); // error
ponieważ rozszerzone ascii nie jest poprawnym utf-8 (mimo że jest to nadal wartość Unicode), podczas gdyunescape('%a9'); // ©
musisz znać swoje dane, gdy używasz decodeURIComponent.decodeURIComponent nie będzie działał
"%C2"
ani żaden pojedynczy bajt,0x7f
ponieważ w utf-8 wskazuje część surogatu. JednakdecodeURIComponent("%C2%A9") //gives you ©
Unescape nie działałby prawidłowo na tym// ©
ORAZ nie zgłosiłby błędu, więc unescape może prowadzić do błędnego kodu, jeśli nie znasz swoich danych.źródło
Używanie
JSON.decode
do tego ma istotne wady, o których musisz wiedzieć:JSON.decode
(po owijanie ich w cudzysłów) będzie błędu, mimo wszystko to są ważne:\\n
,\n
,\\0
,a"a
\\x45
\\u{045}
Istnieją również inne zastrzeżenia. Zasadniczo używanie
JSON.decode
do tego celu jest hackowaniem i nie działa tak, jak można się zawsze spodziewać. Należy trzymać sięJSON
biblioteki do obsługi formatu JSON, a nie operacji na łańcuchach.Niedawno napotkałem ten problem i chciałem solidnego dekodera, więc napisałem go sam. Jest kompletny, dokładnie przetestowany i dostępny tutaj: https://github.com/iansan5653/unraw . Naśladuje standard JavaScript tak dokładnie, jak to możliwe.
Wyjaśnienie:
Źródło ma około 250 linii, więc nie będę go tutaj umieszczać, ale zasadniczo używa następującego Regex, aby znaleźć wszystkie sekwencje specjalne, a następnie analizuje je, używając
parseInt(string, 16)
do dekodowania liczb o podstawie 16, a następnieString.fromCodePoint(number)
do uzyskania odpowiedniego znaku:/\\(?:(\\)|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
Skomentowano (UWAGA: to wyrażenie regularne pasuje do wszystkich sekwencji ucieczki, w tym nieprawidłowych. Jeśli ciąg spowodowałby błąd w JS, zgłasza błąd w mojej bibliotece [tj.
'\x!!'
Spowoduje błąd]):/ \\ # 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
Przykład
Korzystanie z tej biblioteki:
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
źródło