Dekodowanie Kodowanie URL (kodowanie procentowe)


100

Chcę zdekodować kodowanie adresu URL. Czy jest do tego jakieś wbudowane narzędzie, czy ktoś może dostarczyć mi sedkod, który to zrobi?

Szukałem trochę w unix.stackexchange.com i w Internecie, ale nie mogłem znaleźć żadnego narzędzia wiersza poleceń do dekodowania kodowania URL.

Chcę po prostu edytować txtplik, aby:

  • %21 staje się !
  • %23 staje się #
  • %24 staje się $
  • %26 staje się &
  • %27 staje się '
  • %28 staje się (
  • %29 staje się )

I tak dalej.


Odpowiedzi:


107

Znaleziono te linijki Pythona, które robią, co chcesz:

$ alias urldecode='python -c "import sys, urllib as ul; \
    print ul.unquote_plus(sys.argv[1])"'

$ alias urlencode='python -c "import sys, urllib as ul; \
    print ul.quote_plus(sys.argv[1])"'

Przykład

$ urldecode 'q+werty%3D%2F%3B'
q werty=/;

$ urlencode 'q werty=/;'
q+werty%3D%2F%3B

Bibliografia


Wiem to bardzo późno, ale czy mogę to zrobić za pomocą edycji na miejscu?
DisplayName

@DisplayName - dla mnie brzmi jak nowe Q. Poprosiłbym o to i odwołam się do tego.
slm

15
streaming:cat your_lovely_file.csv| python -c "import sys, urllib as ul; [sys.stdout.write(ul.quote_plus(l)) for l in sys.stdin]"
kirill_igum

5
Zauważ, że jest to Python 2; w systemach, w których pythondomyślnie jest 3, spowoduje to błąd. Zmiana pythonna python2pomoc.
Ivan Kolmychek,

4
Dla python3można użyć import urllib.parse as ulzamiast import urllib as ul.
ibotty,

61

sed

Wypróbuj następującą linię poleceń:

$ sed 's@+@ @g;s@%@\\x@g' file | xargs -0 printf "%b"

lub następująca alternatywa przy użyciu echo -e:

$ sed -e's/%\([0-9A-F][0-9A-F]\)/\\\\\x\1/g' file | xargs echo -e

Uwaga: powyższa składnia może nie być konwertowana +na spacje i może zjadać wszystkie znaki nowej linii.


Możesz zdefiniować go jako alias i dodać do plików RC powłoki :

$ alias urldecode='sed "s@+@ @g;s@%@\\\\x@g" | xargs -0 printf "%b"'

Następnie za każdym razem, gdy jej potrzebujesz, po prostu skorzystaj z:

$ echo "http%3A%2F%2Fwww" | urldecode
http://www

Grzmotnąć

Podczas pisania skryptów możesz użyć następującej składni:

input="http%3A%2F%2Fwww"
decoded=$(printf '%b' "${input//%/\\x}")

Jednak powyższa składnia nie będzie +poprawnie obsługiwać plusów ( ), więc musisz zastąpić je spacjami przez sed.

Możesz także użyć następujących funkcji urlencode()i urldecode()funkcji:

urlencode() {
    # urlencode <string>
    local length="${#1}"
    for (( i = 0; i < length; i++ )); do
        local c="${1:i:1}"
        case $c in
            [a-zA-Z0-9.~_-]) printf "$c" ;;
            *) printf '%%%02X' "'$c" ;;
        esac
    done
}

urldecode() {
    # urldecode <string>

    local url_encoded="${1//+/ }"
    printf '%b' "${url_encoded//%/\\x}"
}

Zauważ, że powyżej urldecode()zakłada się, że dane nie zawierają ukośnika odwrotnego.

Oto podobna wersja Joela znaleziona na: https://github.com/sixarm/urldecode.sh


bash + xxd

Funkcja Bash z xxdnarzędziem:

urlencode() {
  local length="${#1}"
  for (( i = 0; i < length; i++ )); do
    local c="${1:i:1}"
    case $c in
      [a-zA-Z0-9.~_-]) printf "$c" ;;
    *) printf "$c" | xxd -p -c1 | while read x;do printf "%%%s" "$x";done
  esac
done
}

Znalezione w pliku gist cdown , również w stackoverflow .


PHP

Za pomocą PHP możesz wypróbować następujące polecenie:

$ echo oil+and+gas | php -r 'echo urldecode(fgets(STDIN));' // Or: php://stdin
oil and gas

Lub tylko:

php -r 'echo urldecode("oil+and+gas");'

Użyj -Rdo wprowadzania wielu linii.


Perl

W Perlu możesz używać URI::Escape.

decoded_url=$(perl -MURI::Escape -e 'print uri_unescape($ARGV[0])' "$encoded_url")

Lub przetworzyć plik:

perl -i -MURI::Escape -e 'print uri_unescape($ARGV[0])' file

awk

Wypróbuj rozwiązanie anonowe :

awk -niord '{printf RT?$0chr("0x"substr(RT,2)):$0}' RS=%..

Uwaga: parametr -njest specyficzny dla GNU awk.

Zobacz: Używanie awk printf do kodu urldecode .

dekodowanie nazw plików

Jeśli chcesz usunąć kodowanie adresu URL z nazw plików, użyj deurlnamenarzędzia z renameutils(np deurlname *.*.).

Zobacz też:


Związane z:


1
awk: Ponieważ korzysta z funkcji bibliotecznej chr(), istnieje duże prawdopodobieństwo, że będzie działać wyłącznie na GNU awk ( gawk). Jednak w tym przypadku nie będzie prawie żadnego odpowiednika POSIX awk, ponieważ -nopcja (dopuszczenie argumentów nie dziesiętnych) JESTawk specjalnością GNU .
syntaxerror

Twój pierwszy sedkod daje mi xargs: argument line too longplik z ≥2164 liniami.
Sparhawk

2
Twoje rozwiązania obejmujące printfnie biorą pod uwagę, że adres URL może zawierać znaki procentu ucieczki, takie jak %25. Przekazujesz je do printf bez uciekania ich do printf z innym znakiem procentowym, takim jak %%.
josch

1
Wersja bash wymaga local LC_ALL=Cu góry, w przeciwnym razie wszystkie szerokie znaki (tj. Japoński, chiński itp.) Nie zostaną poprawnie podzielone na bajty.
Phernost


18

Jest to wbudowana funkcja w standardowej bibliotece Pythona. W Pythonie 2 jest to urllib.unquote.

decoded_url=$(python2 -c 'import sys, urllib; print urllib.unquote(sys.argv[1])' "$encoded_url")

Lub przetworzyć plik:

python2 -c 'import sys, urllib; print urllib.unquote(sys.stdin.read())' <file >file.new &&
mv -f file.new file

W Pythonie 3 jest to urllib.parse.unquote.

decoded_url=$(python3 -c 'import sys, urllib.parse; print(urllib.parse.unquote(sys.argv[1]))' "$encoded_url")

Lub przetworzyć plik:

python3 -c 'import sys, urllib; print(urllib.parse.unquote(sys.stdin.read()))' <file >file.new &&
mv -f file.new file

W Perlu możesz używać URI::Escape.

decoded_url=$(perl -MURI::Escape -e 'print uri_unescape($ARGV[0])' "$encoded_url")

Lub przetworzyć plik:

perl -i -MURI::Escape -e 'print uri_unescape($ARGV[0])' file

Jeśli chcesz trzymać się przenośnych narzędzi POSIX, jest to niewygodne, ponieważ jedynym poważnym kandydatem jest awk, który nie analizuje liczb szesnastkowych. Zobacz Używanie awk printf do urldecode tekstu, aby zapoznać się z przykładami typowych implementacji awk, w tym BusyBox.


10

Jeśli chcesz użyć prostego sedpolecenia, wykonaj następujące czynności:

sed -e 's/%21/!/g' -e 's/%23/#/g' -e 's/%24/$/g' -e 's/%26/\&/g' -e "s/%27/'/g" -e 's/%28/(/g' -e 's/%29/)/g'

Ale wygodniej jest utworzyć skrypt taki jak (powiedzmy sedscript):

s/%21/!/g
s/%23/#/g
s/%24/$/g
s/%26/\&/g
s/%27/'/g
s/%28/(/g
s/%29/)/g

Następnie uruchom sed -f sedscript < old > new, który wyświetli, jak chcesz.


Dla ułatwienia polecenie urlencodejest również dostępne bezpośrednio w gridsite-clientspakiecie, z którego można zainstalować ( sudo apt-get install gridsite-clientsw systemie Ubuntu / Debian).

IMIĘ

    urlencode - konwertuje ciągi znaków do lub z postaci zakodowanej w adresie URL
STRESZCZENIE

    urlencode [-m|-d] string [string ...]

OPIS

    urlencode koduje ciągi znaków zgodnie z RFC 1738.

    Oznacza to, że znaki A- Z a- z 0- 9 . _i -są przekazywane za pośrednictwem niemodyfikowana, ale wszystkie inne znaki są reprezentowane% HH, gdzie HH jest ich dwucyfrowa dużymi literami reprezentacja szesnastkowym ASCII. Na przykład URL http://www.gridpp.ac.uk/staje sięhttp%3A%2F%2Fwww.gridpp.ac.uk%2F

    urlencodekonwertuje każdy znak we wszystkich ciągach podanych w wierszu poleceń. Jeśli podano wiele ciągów, są one łączone z odstępami przed konwersją.

OPCJE
    -m
      Zamiast pełnej konwersji wykonaj GridSite „łagodne kodowanie URL”, w którym AZ az 0-9. = - _ @ i / są przekazywane przez niezmodyfikowane. Powoduje to, że łańcuchy są bardziej czytelne dla człowieka, ale aplikacja musi być przygotowana do utworzenia lub symulacji katalogów sugerowanych przez ukośniki.
    -d
      Wykonuj dekodowanie adresów URL zamiast kodowania, zgodnie z RFC 1738. Ciągi% HH i% hh są konwertowane, a inne znaki są przesyłane w niezmodyfikowany sposób, z wyjątkiem tego, że +jest konwertowany na spację.

Przykład dekodowania adresu URL:

$ urlencode -d "http%3a%2f%2funix.stackexchange.com%2f"
http://unix.stackexchange.com/

$ urlencode -d "Example: %21, %22, . . . , %29 etc"
Example: !, ", . . . , ) etc

Samouczek podczas sed wizyty
Pandya

4
To złe rozwiązanie, ponieważ wymaga twardego kodowania każdej postaci. Przykładem tego problemu jest brak w kodzie często używanej %20sekwencji specjalnej.
Overv

@Overv Właśnie zaktualizowałem
Pandya

Możesz także sprawdzić dokładnie, co s/%26/&/grobi. (Naprawiłem to.)
G-Man,

9

Jedna wkładka Perl:

$ perl -pe 's/\%(\w\w)/chr hex $1/ge'

Przykład:

$ echo '%21%22' |  perl -pe 's/\%(\w\w)/chr hex $1/ge'
!"

1
Ta odpowiedź jest atrakcyjna, gdy nie chcesz zajmować się instalowaniem modułów perla.
Sridhar Sarnobat,

1
Tylko ten, który działał dla mnie elegancko na MacOS.
Qix


7

Nie mogę komentować najlepszej odpowiedzi w tym wątku , więc oto moja.

Osobiście używam tych aliasów do kodowania i dekodowania adresów URL:

alias urlencode='python -c "import urllib, sys; print urllib.quote(  sys.argv[1] if len(sys.argv) > 1 else sys.stdin.read()[0:-1])"'

alias urldecode='python -c "import urllib, sys; print urllib.unquote(sys.argv[1] if len(sys.argv) > 1 else sys.stdin.read()[0:-1])"'

Oba polecenia pozwalają na konwersję danych przekazywanych jako argument wiersza poleceń lub odczytanie go ze standardowego wejścia , ponieważ oba wiersze jednowierszowe sprawdzają, czy istnieją argumenty wiersza polecenia (nawet puste), i przetwarzają je, lub po prostu czytają standardowe wejście w inny sposób.


aktualizacja 2017-05-23 (kodowanie ukośnika)

W odpowiedzi na komentarz @ Bevor.

Jeśli musisz również zakodować ukośnik, po prostu dodaj pusty drugi argument do funkcji cudzysłowu, ukośnik również zostanie zakodowany.

Ostatecznie urlencode alias w bash wygląda następująco:

alias urlencode='python -c "import urllib, sys; print urllib.quote(sys.argv[1] if len(sys.argv) > 1 else sys.stdin.read()[0:-1], \"\")"'

Przykład

$ urlencode "Проба пера/Pen test"
%D0%9F%D1%80%D0%BE%D0%B1%D0%B0%20%D0%BF%D0%B5%D1%80%D0%B0%2FPen%20test

$ echo "Проба пера/Pen test" | urlencode
%D0%9F%D1%80%D0%BE%D0%B1%D0%B0%20%D0%BF%D0%B5%D1%80%D0%B0%2FPen%20test

$ urldecode %D0%9F%D1%80%D0%BE%D0%B1%D0%B0%20%D0%BF%D0%B5%D1%80%D0%B0%2FPen%20test
Проба пера/Pen test

$ echo "%D0%9F%D1%80%D0%BE%D0%B1%D0%B0%20%D0%BF%D0%B5%D1%80%D0%B0%2FPen%20test" | urldecode
Проба пера/Pen test

$ urlencode "Проба пера/Pen test" | urldecode
Проба пера/Pen test

$ echo "Проба пера/Pen test" | urlencode | urldecode
Проба пера/Pen test

1
Nie koduje ukośników.
Bevor

@Bevor: przykład?
DIG mbl

Dodaj ukośnik do urlencode „Проба пера” -> wynik: Slash nie jest zakodowany.
Bevor

1
@Bevor: Masz rację. Dziękuję za Twój komentarz. Zmienię również swoją odpowiedź, aby odzwierciedlić w niej twój komentarz.
DIG mbl

4

I inne podejście do Perla:

#!/usr/bin/env perl
use URI::Encode;
my $uri     = URI::Encode->new( { encode_reserved => 0 } );
while (<>) {

    print $uri->decode($_)
}

Będziesz musiał zainstalować URI::Encodemoduł. Na moim Debianie mogłem po prostu biec

sudo apt-get install liburi-encode-perl

Następnie uruchomiłem powyższy skrypt na pliku testowym zawierającym:

http://foo%21asd%23asd%24%26asd%27asd%28asd%29

Wynik był (zapisałem skrypt jako foo.pl):

$ ./foo.pl
http://foo!asd#asd$&asd'asd(asd)

3

Odpowiedź w powłoce (głównie Posix):

$ input='%21%22'
$ printf "`printf "%s\n" "$input" | sed -e 's/+/ /g' -e 's/%\(..\)/\\\\x\1/g'`"
!"

Wyjaśnienie:

  • -e 's/+/ /gprzekształca każdą +w przestrzeni (jak opisano w normie kodowania URL)
  • -e 's/%\(..\)/\\\\x\1/g'przekształcić każdy %XXw \\xXX. Zauważ, że jeden z nich \zostanie usunięty przez cytowanie reguł.
  • Wewnętrzny printf jest po to, aby przekazać dane wejściowe do sed. Możemy go zastąpić dowolnym innym mechanizmem
  • Zewnętrzny printf interpretuje \\xXXsekwencje i wyświetla wynik.

Edytować:

Ponieważ %należy zawsze interpretować w adresach URL, można uprościć tę odpowiedź. W dodatku, myślę, że jest czystsze używać xargszamiast małe cudzysłowy (dzięki @josch).

$ input='%21%22+%25'
$ printf "%s\n" "$input" | sed -e 's/+/ /g; s/%/\\x/g' | xargs -0 printf
!" %

Niestety (jak zauważył @josch) żadne z tych rozwiązań nie jest zgodne z Posix, ponieważ \xsekwencja ucieczki nie jest zdefiniowana w Posix.


Witamy w U&L. Być może mógłbyś wyjaśnić tę odpowiedź i jak to działa. Zasadniczo wolimy, aby nasze odpowiedzi były długie i zawierały szczegółowe informacje, a nie tylko fragmenty kodu.
slm

Naprawdę podoba mi się ta odpowiedź, ponieważ jest kompleksowa, przenośna i nie wymaga dodatkowych cięższych programów zewnętrznych, takich jak Perl lub Python. Działa dla mnie dobrze.
Steve Wills,

1
Świetne rozwiązanie. I jeszcze krótsze i bardziej inteligentne: ... | sed 's/+/ /g;s/%\(..\)/\\\\x\1/g'. W -erzeczywistości tutaj można pominąć tę opcję ...
składniaerror

1
@ josch Masz rację, printfjest wbudowany dashi nie rozpoznaje \xucieczki. Możesz użyć /usr/bin/printfzamiast printf, aby to zadziałało. Zwykle powinieneś być w stanie korzystać command printf, ale wydaje się, że nie działa tak, jak powinien. Nadal używa wbudowanego.
Jérôme Pouiller

1
@ Jezz rzeczywiście wsparcie dla \xucieczki nie jest częścią POSIX: pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html Podczas moich testów widziałem inny problem. Możesz zamienić ..wyrażenie regularne na, [a-zA-Z0-9][a-zA-Z0-9]ponieważ w przeciwnym razie wprowadzanie typu „%%%” zakończy się niepowodzeniem. Dodałem również s/%/%%/gna końcu, aby upewnić się, że nie ma wartości procentowych dla printf.
josch

1

Tylko skorupa:

$ x='a%20%25%e3%81%82';printf "${x//\%/\\x}"
a %あ

Dodaj --lub, %baby nie traktować argumentów rozpoczynających się od myślnika jako opcji.

W Zsh ${x//%/a}dodaje asię do końca, ale ${x//\%/a}zastępuje %się a.


1

Oto odpowiednie fragmenty z innego skryptu (który bezwstydnie ukradłem z mojego skryptu pobierania youtube.com z innej odpowiedzi) , który napisałem wcześniej. Używa sedi powłoki do zbudowania działającego kodu urld.

set \! \" \# \$ \% \& \' \( \) \* \ \+ \, \/ \: \; \= \? \@ \[ \]
for c do set "$@" "'$c" "$c"; shift; done
curl -s "$url" | sed 's/\\u0026/\&/g;'"$(
    printf 's/%%%X/\\%s/g;' "$@"
)"

Nie przysięgam, że jest obszerny - i faktycznie w to wątpię - ale z pewnością poradził sobie z youtube.


1

Oto funkcja BASH, aby dokładnie to zrobić:

function urldecode() {
        echo -ne $(echo -n "$1" | sed -E "s/%/\\\\x/g")
}

działa jak urok
AbdElraouf Sabri

0

Inne rozwiązanie wykorzystujące ruby ​​(zaakceptowana odpowiedź python nie działała dla mnie)

alias urldecode='ruby -e "require \"cgi\"; puts CGI.unescape(ARGV[0])"'
alias urlencode='ruby -e "require \"cgi\"; puts CGI.escape(ARGV[0])"'

Przykład

$ urldecode 'q+werty%3D%2F%3B'
q werty=/;

$ urlencode 'q werty=/;'
q+werty%3D%2F%3B
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.