Decodificação de codificação de URL (porcentagem de codificação)


101

Quero decodificar a codificação de URL, existe alguma ferramenta interna para fazer isso ou alguém poderia me fornecer um sedcódigo que faça isso?

Pesquisei um pouco no unix.stackexchange.com e na Internet, mas não consegui encontrar nenhuma ferramenta de linha de comando para decodificar a codificação de URL.

O que eu quero fazer é simplesmente editar um txtarquivo para que:

  • %21 torna-se !
  • %23 torna-se #
  • %24 torna-se $
  • %26 torna-se &
  • %27 torna-se '
  • %28 torna-se (
  • %29 torna-se )

E assim por diante.


Respostas:


107

Encontrei os liners one Python que fazem o que você deseja:

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

Exemplo

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

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

Referências


Eu sei disso muito tarde, mas existe alguma maneira de fazer isso com a edição no local?
— DisplayName 4/04

@DisplayName - soa como um novo Q para mim. Eu pediria e referenciaria este.
— 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 02/12/2015

5
Observe que este é um Python 2; nos sistemas onde pythoné 3 por padrão, isso resultará em erro. Mudando pythonpara python2ajuda.
— Ivan Kolmychek

4
Para python3você pode usar em import urllib.parse as ulvez de import urllib as ul.
— ibotty

61

sed

Tente a seguinte linha de comando:

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

ou a seguinte alternativa usando echo -e:

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

Nota: A sintaxe acima pode não se converter +em espaços e pode comer todas as novas linhas.


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 acima urldecode()assume que os dados não contêm barra invertida.

Aqui está a versão semelhante de Joel encontrada em: https://github.com/sixarm/urldecode.sh


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 .


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

awk

Experimente a solução anon :

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

Nota: O parâmetro -né específico ao GNU awk.

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:


Palavras-chave:


1
awk: Como isso faz uso de uma função de biblioteca chr(), há uma alta probabilidade de que ele funcione apenas no GNU awk ( gawk). No entanto, nesse caso, dificilmente haverá equivalente para o POSIX awk, porque a -nopção (permitindo argumentos não decimais) É uma awkespecialidade do GNU .
— SyntaxError

Seu primeiro sedcódigo fornece xargs: argument line too longum arquivo com ≥2164 linhas.
— Sparhawk

2
Suas soluções envolvendo printfnão levam em consideração que o URL pode conter sinais de porcentagem de escape como %25. Você os passa para printf sem escapá-los para printf com outro sinal de porcentagem como %%.
— Josch

1
A versão do bash requer local LC_ALL=Cna parte superior, caso contrário, todos os caracteres largos (por exemplo, japonês, chinês etc.) não são divididos corretamente em bytes.
— Phernost


18

Existe uma função interna para isso na biblioteca padrão do Python. No Python 2, é urllib.unquote.

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

Ou para processar um arquivo:

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

No Python 3, é urllib.parse.unquote.

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

Ou para processar um arquivo:

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

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

Se você deseja manter as ferramentas portáteis POSIX, é complicado, porque o único candidato sério é o awk, que não analisa números hexadecimais. Consulte Usando o awk printf para codificar o texto para obter exemplos de implementações comuns do awk, incluindo o BusyBox.


10

Se você deseja usar um sedcomando simplificado , use o seguinte:

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'

Mas é mais conveniente criar um script como (digamos sedscript):

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

Em seguida sed -f sedscript < old > new, execute , que será exibido conforme desejado.


Para facilitar, o comando urlencodetambém está disponível diretamente no gridsite-clientspacote pode ser instalado a partir de ( sudo apt-get install gridsite-clientsno sistema Ubuntu / Debian).

NOME

    urlencode - converte seqüências de caracteres de ou para um formulário codificado por URL
SINOPSE

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

DESCRIÇÃO

    urlencode codifica seqüências de acordo com a RFC 1738.

    Ou seja, os caracteres A- Z a- z 0- 9 . _e -são passados ​​sem modificação, mas todos os outros caracteres são representados como% HH, em que HH é sua representação ASCII hexadecimal em maiúscula e dois dígitos. Por exemplo, o URL http://www.gridpp.ac.uk/se tornahttp%3A%2F%2Fwww.gridpp.ac.uk%2F

    urlencodeconverte cada caractere em todas as strings fornecidas na linha de comando. Se várias seqüências de caracteres forem fornecidas, elas serão concatenadas com a separação de espaços antes da conversão.

OPÇÕES
    -m
      Em vez da conversão completa, faça no GridSite "codificação moderada de URL" na qual AZ az 0-9. = - _ @ e / são passados ​​sem modificação. Isso resulta em seqüências de caracteres um pouco mais legíveis por humanos, mas o aplicativo deve estar preparado para criar ou simular os diretórios implícitos em qualquer barra.
    -d
      Decodificação de URL em vez de codificação, de acordo com a RFC 1738.% HH e% hh são convertidas e outros caracteres são passados ​​sem modificação, com a exceção que +é convertida em espaço.

Exemplo de URL de decodificação:

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

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

Para tutorial em sed visita
— Pandya

4
Essa é uma péssima solução, pois exige a codificação de todos os caracteres. Esse problema é exemplificado pelo código que está faltando na %20seqüência de escape usada com frequência .
— Overv

@Overv que eu acabei de revisar
— Pandya

Além disso, convém verificar o que s/%26/&/gfaz. (I fixa-lo.)
— G-Man

9

Perl um forro:

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

Exemplo:

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

1
Essa resposta é atraente quando você não deseja lidar com a instalação de módulos perl.
— Sridhar Sarnobat

1
Único que funcionou elegantemente para mim no MacOS.
— Qix 27/03


7

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.


update 23-05-2017 (codificação com barra)

Em resposta ao comentário do @ Bevor.

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
Não codifica barras.
— Bevor 15/05

@ Bevor: Exemplo?
— DIG MBL

Adicione uma barra ao código de URL "Проба пера" -> resultado: a barra não é codificada.
— Bevor

1
@ Bevor: Você está certo. Obrigado pelo seu comentário. Também mudarei minha resposta para refletir seu comentário.
— DIG mbl 23/05

4

E outra abordagem Perl:

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

    print $uri->decode($_)
}

Você precisará instalar o URI::Encodemódulo. No meu Debian, eu poderia simplesmente executar

sudo apt-get install liburi-encode-perl

Em seguida, executei o script acima em um arquivo de teste contendo:

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

O resultado foi (eu salvei o script como foo.pl):

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

3

Uma resposta no shell (principalmente Posix):

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

Explicação:

  • -e 's/+/ /gtransforma cada uma +no espaço (conforme descrito na norma de codificação de URL)
  • -e 's/%\(..\)/\\\\x\1/g'transformar cada %XXno \\xXX. Observe que um dos \itens será removido pelas regras de citação.
  • O printf interno está lá apenas para passar a entrada para sed. Podemos substituí-lo por qualquer outro mecanismo
  • A impressão externa interpreta \\xXXseqüências e exibe o resultado.

Editar:

Como %sempre deve ser interpretado nos URLs, é possível simplificar esta resposta. Além disso, acho que é mais limpo usar em xargsvez de aspas (graças a @josch).

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

Infelizmente, (como @josch notou), nenhuma dessas soluções é compatível com Posix, pois a \xsequência de escape não está definida no Posix.


Bem-vindo ao U&L. Talvez você possa explicar essa resposta e como ela funciona. Geralmente, preferimos que nossas respostas sejam longas, com detalhes, não apenas trechos de código.
— slm

Eu realmente gosto dessa resposta porque é abrangente, portátil e não requer programas externos mais pesados, como perl ou python. Funciona bem para mim.
— Steve Wills

1
Ótima solução. E ainda mais curto e mais inteligente: ... | sed 's/+/ /g;s/%\(..\)/\\\\x\1/g'. A -eopção pode ser omitida aqui, na verdade ...
— SyntaxError

1
@josch Você está certo, printfé um embutido dashe não reconhece como \xescapar. Você pode usar em /usr/bin/printfvez de printfpara fazê-lo funcionar. Normalmente, você deve poder usar command printf, mas parece não funcionar como deveria. Ele continua usando o built-in.
— Jérôme Pouiller 14/09/16

1
@ Jezz, de fato, o suporte para \xescapar não faz parte do POSIX: pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html Durante meus testes, vi outro problema. Você pode substituir seu ..regex [a-zA-Z0-9][a-zA-Z0-9]porque, caso contrário, a entrada como '%%%' falhará. Eu também adicionei s/%/%%/gno final para garantir uma porcentagem de escape para printf.
— Josch

1

Somente shell:

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

Adicione --ou %bpara impedir que os argumentos que começam com um traço sejam tratados como opções.

No zsh ${x//%/a}adiciona aao final, mas ${x//\%/a}substitui %por a.


1

Aqui estão os bits relevantes de outro script (que eu roubei descaradamente do meu script de download do youtube.com de outra resposta) que eu escrevi antes. Ele usa sede o shell para criar um código de funcionamento.

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

Eu não juro que é abrangente - e, de fato, duvido -, mas ele segurou o youtube com certeza.


1

Aqui está uma função BASH para fazer exatamente isso:

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

funciona como um encanto
— AbdElraouf Sabri

0

Outra solução usando ruby ​​(a resposta em python aceita não estava funcionando para mim)

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

Exemplo

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

$ urlencode 'q werty=/;'
q+werty%3D%2F%3B
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.