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.