Jak mogę kodować i dekodować ciągi zakodowane procentowo w wierszu poleceń?

31

Jak mogę kodować i dekodować ciągi zakodowane procentowo (URL zakodowane) w wierszu poleceń?

Szukam rozwiązania, które może to zrobić:

$ percent-encode "ændrük"
%C3%A6ndr%C3%BCk
$ percent-decode "%C3%A6ndr%C3%BCk"
ændrük
ændrük
źródło
Czy chcesz uwzględnić także różne kodowania? %E6ndr%FCkdla mnie nie wygląda jak (standardowy) UTF8. Czy to tylko przykład?
umów się
@arrange Dzięki za złapanie tego. Najwyraźniej wybrałem złe jabłko wśród wyników wyszukiwania konwerterów online.
ændrük
Aby uzyskać nazwy plików, zobacz: Jak usunąć kodowanie URI w nazwach plików .
kenorb

Odpowiedzi:

35

Te polecenia robią, co chcesz:

python -c "import urllib, sys; print urllib.quote(sys.argv[1])" æ
python -c "import urllib, sys; print urllib.unquote(sys.argv[1])" %C3%A6

Jeśli chcesz przestrzeniach kodują jak +wymienić urllib.quotez urllib.quote_plus.

Zgaduję, że będziesz chciał je pseudonim ;-)

Stefano Palazzo
źródło
1
Co to za znak… na końcu pierwszego wiersza? Edycja: odpowiadając sobie - rozumiem, to tylko jeden znak UTF8, który ma być zakodowany, na przykład w celu :-)
TMG
1
co powiesz na python3?
RicardoE
@ RicardoE sprawdź tę odpowiedź .
Pablo A
27

muszla

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

$ echo "%C3%A6ndr%C3%BCk" | sed 's@+@ @g;s@%@\\x@g' | xargs -0 printf "%b"
ændrük

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 twoja urldecode () zakłada, że ​​dane nie zawierają ukośnika odwrotnego.


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 .


Pyton

Spróbuj zdefiniować następujące aliasy:

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])"'

Stosowanie:

$ urlencode "ændrük"
C%26ndrC%3Ck
$ urldecode "%C3%A6ndr%C3%BCk"
ændrük

Źródło: ruslanspivak


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

sed

Używanie sedmożna osiągnąć poprzez:

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

awk

Wypróbuj rozwiązanie anonowe :

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

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:

kenorb
źródło
Bash + xxd wersja nie działa z ciągów, które zawierają %, może można zastąpić printf "$c"z printf "%c" "$c"? Innym problemem jest to, że niektóre znaki nie będące kodami ASCII nie są zakodowane (np. ä) W niektórych ustawieniach języka, może dodać funkcję export LC_ALL=Cw (co nie powinno wpływać na nic poza funkcją)?
12431234123412341234123
8

Kodowane w procentach zastrzeżone znaki URI i znaki spoza ASCII

jq -s -R -r @uri

-s( --slurp) odczytuje wiersze wejściowe do tablicy, a -s -R( --slurp --raw-input) odczytuje dane wejściowe w jednym ciągu. -r( --raw-output) wyświetla zawartość ciągów zamiast literałów JSON.

Kodowanie procentowe wszystkich znaków

xxd -p|tr -d \\n|sed 's/../%&/g'

tr -d \\nusuwa źródła linii, które są dodawane xxd -ppo każdych 60 znakach.

Kodowanie procentowe wszystkich znaków oprócz znaków alfanumerycznych ASCII w języku Bash

eu () {
    local LC_ALL=C c
    while IFS= read -r -n1 -d '' c
    do 
        if [[ $c = [[:alnum:]] ]]
        then 
            printf %s "$c"
        else
            printf %%%02x "'$c"
        fi
    done
}

Bez -d ''tego pomijałoby podawanie linii i zerowe bajty. Bez IFS=tego byłoby zastąpić znaki IFSz %00. Bez LC_ALL=Ctego byłoby na przykład wymienić ze %3042w UTF-8.

nisetama
źródło
5

Rozwiązanie Pure Bash do dekodowania :

$ a='%C3%A6ndr%C3%BCk'
$ echo -e "${a//%/\\x}"
ændrük
loentar
źródło
4

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 2015-07-16 (pusty 1. arg)

... zgodnie z komentarzem @muru.

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

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
DIG mbl
źródło
1
Myślę, że sys.argv[1] if len(sys.argv) > 1 else sys.stdin.read()[0:-1]może być bardziej odpowiednie. Zwłaszcza jeśli użyjesz tego w skryptach i przypadkowo podasz pusty pierwszy argument.
muru
Zgodnie z komentarzem @muru zmieniłem sprawdzanie argumentu w wierszu poleceń. To było: len(sys.argv) < 2 and sys.stdin.read()[0:-1] or sys.argv[1] Teraz: sys.argv[1] if len(sys.argv) > 1 else sys.stdin.read()[0:-1] To znaczy, jeśli pierwszy pusty argument jest pusty, polecenie nie czeka na dane wejściowe ze standardowego wejścia, ale przetwarza pusty argument.
DIG mbl
2

Znalazłem pakiet, renameutilsktóry zawiera narzędzie, deurlnamektóre może zmienić nazwę pliku zawierającego znaki „zakodowane procentowo”.

Niestety, nie dekoduje standardowego wejścia lub opcji wiersza poleceń, a jedynie zmienia nazwę pliku, więc musisz utworzyć plik zastępczy, aby uzyskać dekodowanie (nazwę pliku o zmienionej nazwie), ale w przypadku niektórych skryptów bash proces można zautomatyzować .

Brak informacji na temat części kodującej, nawet ponieważ może być wątpliwe, które znaki należy zakodować. Tylko nie-ASCII?

Myślę, że powinno być jakieś lepsze narzędzie / metoda.

enzotib
źródło
1

Podobny do Ansano Stefano, ale w Pythonie 3:

python -c "import urllib.parse, sys; print(urllib.parse.quote(sys.argv[1]))" æ
python -c "import urllib.parse, sys; print(urllib.parse.unquote(sys.argv[1]))" %C3%A6

Aby zakodować również ukośniki:

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

Więcej informacji o różnicy tutaj .

Pablo A.
źródło
0

Oto funkcja POSIX Awk do kodowania:

function encodeURIComponent(str, j, q) {
  while (y++ < 125) z[sprintf("%c", y)] = y
  while (y = substr(str, ++j, 1))
    q = y ~ /[[:alnum:]_.!~*\47()-]/ ? q y : q sprintf("%%%02X", z[y])
  return q
}

Przykład

Steven Penny
źródło