Jak zastąpić wszystkie zakodowane procentowo podciągi UTF-8 zwykłym tekstem UTF-8?

9

Mam plik HTML z dużą ilością zakodowanego w% tekstu UTF-8 w adresach URL.

Na przykład „% D1% 80% D0% B5% D1% 81% D1% 83% D1% 80% D1% 81% D1% 8B” oznacza „ресурсы” („zasoby” w języku rosyjskim).

Zadanie polega na zastąpieniu wszystkich takich podciągów czytelnym tekstem UTF-8.

Aby uprościć zadanie, możemy uznać, że %w pliku nie ma innego użycia znaku. Cyfry literowe mogą być zarówno dużymi, jak i małymi literami.

Podejrzewam, że można to zrobić elegancko sed, perl, awkczy coś, ale nie wiem jak.

Wygląda na to, że ta aplikacja internetowa rozwiązuje problem z wklejanym tam tekstem.

Ivan
źródło

Odpowiedzi:

9

Z bash, zsh, GNU echo lub niektórych implementacjach ksh W niektórych systemach może to być dekodowane po prostu echo -epo wymianie wszystkich %z \x.

url_encoded_string="%D1%80%D0%B5%D1%81%D1%83%D1%80%D1%81%D1%8B"
temp_string=${url_encoded_string//%/\\x}

printf '%s\n' "$temp_string"
# output: \xD1\x80\xD0\xB5\xD1\x81\xD1\x83\xD1\x80\xD1\x81\xD1\x8B

echo -e "$temp_string"
# output: ресурсы

(Zakłada, że ​​sam łańcuch nie zawiera znaków odwrotnego ukośnika i nie jest jedną z opcji obsługiwanych przez twoje echopolecenie)

Jak zauważa także @JoshLee, można uniknąć „zastrzeżenia dotyczącego echa” poprzez bezpośrednie użycie:

printf ${url_encoded_string//%/\\x}

zamiast tego bezpośrednio za pierwszym poleceniem.

LiuYan 刘 研
źródło
Zauważ, że to eleganckie rozwiązanie będzie działać z każdym . Kodowania, nie tylko UTF-8 (czyli pozbyć się kodowań dla ~ i inni Kolejny trik, aby dodać do mojego przybornika Dzięki.!
vonbrand
5

Z perlem:

perl -pe 's/%([0-9A-F]{2})/pack"H2",$1/gei'

Lub z URI::Escape:

perl -MURI::Escape -pe '$_=uri_unescape$_'
Stéphane Chazelas
źródło
Uwielbiam to, ponieważ mogę to zrobić $_ dowolnie
Nemo
@Nemo, $_tutaj to perljest $_, nie bash's. W połączeniu z -popcją, wyrażenie perla jest uruchamiane dla każdego rekordu wejściowego (rekordy odczytywane z plików podanych jako argument lub stdin, jeśli nie podano argumentu), z bieżącym rekordem zapisanym w $_. To jest podobne do awk„s $0.
Stéphane Chazelas
0

Istnieje program o nazwie, convmvktóry może ci pomóc.

Po prostu użyj convmv --unescape /some_path/target_file. Zrobi to na sucho.

Po potwierdzeniu użyj, convmv --notest --unescape /some_path/target_fileaby kontynuować.

Strona główna tego programu to: http://j3e.de/linux/convmv/

Star Brilliant
źródło