Como codificar e decodificar seqüências de caracteres codificadas por cento na linha de comando?


31

Como posso codificar e decodificar seqüências de caracteres com porcentagem codificada (URL codificada) na linha de comando?

Estou procurando uma solução que possa fazer isso:

$ percent-encode "ændrük"
%C3%A6ndr%C3%BCk
$ percent-decode "%C3%A6ndr%C3%BCk"
ændrük

Deseja incorporar codificações diferentes também? %E6ndr%FCknão parece UTF8 (padrão) para mim. Ou é apenas um exemplo?
organize

@range Obrigado por pegar isso. Aparentemente, escolhi a maçã ruim entre os resultados da pesquisa de conversores on-line.
19411

Respostas:


35

Estes comandos fazem o que você deseja:

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

Se você deseja codificar espaços como +, substitua urllib.quotepor urllib.quote_plus.

Eu estou supondo que você queira apelidá-los ;-)


1
Qual é esse caractere no final da primeira linha? Edit: respondendo a mim mesmo - tem isso, é apenas uma única UTF8 caráter a-ser-codificado corda por exemplo propósito :-)
TMG

1
e quanto a python3?
RicardoE

@RicardoE verifique esta resposta .
Pablo A

27

Concha

Tente a seguinte linha de comando:

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

Você pode defini-lo como alias e adicioná-lo aos seus arquivos shell rc :

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

Depois, sempre que precisar, basta:

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

bater

Ao criar scripts, você pode usar a seguinte sintaxe:

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

No entanto, a sintaxe acima não manipula as vantagens ( +) corretamente, então você deve substituí-las por espaços por sed.

Você também pode usar o seguinte urlencode()e urldecode()funções:

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}"
}

Observe que seu urldecode () assume que os dados não contêm barra invertida.


bash + xxd

Função Bash com xxdferramenta:

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
}

Encontrado no arquivo gist do cdown , também no stackoverflow .


Python

Tente definir os seguintes aliases:

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

Uso:

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

Fonte: ruslanspivak


PHP

Usando o PHP, você pode tentar o seguinte comando:

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

ou apenas:

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

Use -Rpara entrada de várias linhas.


Perl

No Perl você pode usar URI::Escape.

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

Ou para processar um arquivo:

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

sed

O uso sedpode ser conseguido por:

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

awk

Experimente a solução anon :

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

Consulte: Usando o awk printf para codificar o texto .


decodificando nomes de arquivo

Se você precisar remover a codificação de URL dos nomes dos arquivos, use a deurlnameferramenta de renameutils(por exemplo deurlname *.*).

Veja também:


Relacionado:


A versão do bash + xxd não funciona com cadeias que contêm um %, talvez você possa substituir printf "$c"por printf "%c" "$c"? Um outro problema é que alguns caracteres não ASCII não são codificados (como ä) em algumas configurações de idioma, talvez adicione um export LC_ALL=Cna função (que não deve afetar nada fora da função)?
12431234123412341234123 07/10

8

Caracteres URI reservados com codificação percentual e caracteres não ASCII

jq -s -R -r @uri

-s( --slurp) lê as linhas de entrada em uma matriz e -s -R( --slurp --raw-input) lê a entrada em uma única sequência. -r( --raw-output) gera o conteúdo das strings em vez dos literais JSON.

Codificar por cento todos os caracteres

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

tr -d \\nremove os feeds de linha adicionados xxd -papós cada 60 caracteres.

Codificar por cento todos os caracteres, exceto caracteres alfanuméricos ASCII no 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
}

Sem -d ''isso, pularia as alimentações de linha e bytes nulos. Sem IFS=isso, substituiria os caracteres IFSpor %00. Sem LC_ALL=Cisso, por exemplo, seria substituído por %3042um código de idioma UTF-8.


5

Solução de bash pura apenas para decodificação :

$ a='%C3%A6ndr%C3%BCk'
$ echo -e "${a//%/\\x}"
ændrük

4

Não posso comentar sobre a melhor resposta neste tópico , então aqui está o meu.

Pessoalmente, eu uso esses aliases para codificação e decodificação de 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])"'

Ambos os comandos permitem converter dados, passados ​​como um argumento de linha de comando ou lê-los a partir da entrada padrão , porque as duas linhas verificam se há argumentos de linha de comando (mesmo os vazios) e os processam ou apenas os leem da entrada padrão.

atualização 16/07/2015 (vazio 1º argumento)

... de acordo com o comentário do @muru.

atualizar 2017-05-28 (codificação de barra)

Se você também precisar codificar a barra, basta adicionar um segundo argumento vazio à função de cotação, a barra também será codificada.

Então, finalmente, o urlencode alias no bash fica assim:

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

Exemplo

$ 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
Eu acho que sys.argv[1] if len(sys.argv) > 1 else sys.stdin.read()[0:-1]pode ser mais apropriado. Especialmente se você usar isso em scripts e acidentalmente fornecer um primeiro argumento vazio.
muru

Conforme comentário do @muru, mudei a verificação de um argumento na linha de comando. Era: len(sys.argv) < 2 and sys.stdin.read()[0:-1] or sys.argv[1] Agora: sys.argv[1] if len(sys.argv) > 1 else sys.stdin.read()[0:-1] isto é, se houver mesmo um primeiro argumento vazio, o comando não espera pela entrada da entrada padrão, mas processa um argumento vazio.
DIG MBL

2

Encontrei um pacote, renameutilsque contém o utilitário deurlnameque é capaz de renomear um arquivo contendo caracteres "codificados por cento".

Infelizmente, ele não decodifica stdin ou uma opção de linha de comando, mas apenas renomeia um arquivo; portanto, você deve criar um arquivo fictício para obter a decodificação (o nome do arquivo renomeado), mas com alguns scripts de bash, o processo pode ser automatizado. .

Nenhuma informação sobre a parte de codificação, mesmo porque pode ser questionável quais caracteres codificar. Apenas não ASCII?

Eu acho que deveria haver alguma ferramenta / método melhor.


1

Semelhante ao Stefano ansqer, mas em Python 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

Para codificar também barras:

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

Mais informações sobre a diferença aqui .


0

Aqui está uma função POSIX Awk para codificação:

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
}

Exemplo

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.