Estou tentando escrever um script bash para teste que usa um parâmetro e o envia através de curl para o site. Preciso codificar o valor do URL para garantir que os caracteres especiais sejam processados corretamente. Qual é a melhor maneira de fazer isso?
Aqui está o meu script básico até agora:
#!/bin/bash
host=${1:?'bad host'}
value=$2
shift
shift
curl -v -d "param=${value}" http://${host}/somepath $@
Respostas:
Use
curl --data-urlencode
; deman curl
:Exemplo de uso:
Veja a página de manual para mais informações.
Isso requer a curvatura 7.18.0 ou mais recente (lançada em janeiro de 2008) . Use
curl -V
para verificar qual versão você possui.Você também pode codificar a string de consulta :
fonte
curl -G --data-urlencode "blah=df ssdf sdf" --data-urlencode "blah2=dfsdf sdfsd " http://whatever.com/whatever
curl --data-urlencode "description=![image]($url)" www.example.com
. Alguma idéia do porquê? `"
the‽Aqui está a resposta BASH pura.
Você pode usá-lo de duas maneiras:
[editado]
Aqui está a função rawurldecode () correspondente, que - com toda a modéstia - é incrível.
Com o conjunto de correspondência, agora podemos executar alguns testes simples:
E se você realmente acha que precisa de uma ferramenta externa (bem, ela será muito mais rápida e poderá fazer arquivos binários e coisas assim ...) Encontrei isso no meu roteador OpenWRT ...
Onde url_escape.sed era um arquivo que continha estas regras:
fonte
Jogging «à l'Hèze»
geraJogging%20%abà%20l%27Hèze%bb
que não pode ser alimentada por JSdecodeURIComponent
:(\u0144
vir um caractere como ń ( ), ele produzirá% 144, ╡ (\u2561
) será% 2561. As respostas corretas codificadas para essas matérias-primas seriam% C5% 84% 0A e% E2% 95% A1, respectivamente.Use o
URI::Escape
módulo e auri_escape
função do Perl na segunda linha do seu script bash:Editar: Corrija os problemas de citação, conforme sugerido por Chris Johnsen nos comentários. Obrigado!
fonte
echo
, pipe e<>
), e agora funciona mesmo quando $ 2 contém um apóstrofo ou aspas duplas. Obrigado!echo
:value="$(perl -MURI::Escape -e 'print uri_escape($ARGV[0]);' "$2")"
Outra opção é usar
jq
(como um filtro):-R
(--raw-input
) trata as linhas de entrada como seqüências de caracteres em vez de analisá-las como JSON e-sR
(--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.Se a entrada não for a saída de outro comando, você poderá armazená-la em uma
jq
variável de cadeia:-n
(--null-input
) não lê entrada e--arg name value
armazenavalue
na variávelname
como uma sequência. No filtro,$name
(entre aspas simples, para evitar a expansão pelo shell), referencia a variávelname
.Embrulhado como uma função Bash, isso se torna:
Ou esse percentual codifica todos os bytes:
fonte
curl
para codificar que funciona e se o bash tiver um built-in que seria aceitável - masjq
parece ser o ajuste certo, estou longe de atingir o nível de conforto com esta ferramenta)@uri
não é alguma variável, mas um filtro jq literal usado para formatar seqüências de caracteres e escapar; veja jq o manual para mais detalhes (desculpe, nenhuma ligação direta, é necessário procurar@uri
na página ...)printf "http://localhost:8082/" | jq -sRr '@uri'
por uma questão de integridade, muitas soluções usando
sed
ouawk
traduzem apenas um conjunto especial de caracteres e, portanto, são muito grandes em tamanho de código e também não traduzem outros caracteres especiais que devem ser codificados.uma maneira segura de codificar por URL seria codificar apenas cada byte - mesmo aqueles que seriam permitidos.
O xxd está cuidando aqui para que a entrada seja tratada como bytes e não como caracteres.
editar:
O xxd vem com o pacote vim-common no Debian e eu estava em um sistema em que não estava instalado e não queria instalá-lo. A alternativa é usar
hexdump
o pacote bsdmainutils no Debian. De acordo com o gráfico a seguir, bsdmainutils e vim-common devem ter uma probabilidade quase igual de instalação:http://qa.debian.org/popcon-png.php?packages=vim-common%2Cbsdmainutils&show_installed=1&want_legend=1&want_ticks=1
mas, no entanto, aqui uma versão que usa em
hexdump
vez dexxd
e permite evitar atr
chamada:fonte
xxd -plain
deve acontecer DEPOIStr -d '\n'
!\n
caractere será traduzido porxxd -plain
para0a
. Não tome minha palavra para ela, tente você mesmo:echo -n -e '\n' | xxd -plain
Isto prova que o seutr -d '\n'
é inútil aqui como não pode haver qualquer\n
depoisxxd -plain
Segundo,echo foobar
adiciona seu próprio\n
personagem no final da cadeia de caracteres, por issoxxd -plain
não é alimentado comfoobar
como esperado, mas comfoobar\n
. então oxxd -plain
converte em alguma sequência de caracteres que termina0a
, tornando-o inadequado para o usuário. Você pode adicionar-n
aecho
resolvê-lo.xxd
chamada pertence à frente datr -d
chamada. Ele pertence a ele para que qualquer nova linhafoobar
seja traduzida porxxd
. Atr -d
seguir àxxd
chamada é para remover as novas linhas que o xxd produz. Parece que você nunca tem foobar por tempo suficiente, o quexxd
produz novas linhas, mas, para entradas longas, ele o fará. Então otr -d
é necessário. Em contraste com sua suposição,tr -d
NÃO foi para remover novas linhas da entrada, mas daxxd
saída. Eu quero manter as novas linhas na entrada. Seu único ponto válido é que esse eco adiciona uma nova linha desnecessária.echo -n
que eu estava realmente faltandoUma das variantes, pode ser feia, mas simples:
Aqui está a versão one-liner, por exemplo (como sugerido por Bruno ):
fonte
date
comando ...date | curl -Gso /dev/null -w %{url_effective} --data-urlencode @- "" | cut -c 3-
(Você tem quecut
os 2 primeiros caracteres fora, porque a saída de onda é um tecnicamente um URL relativo com uma string de consulta.)%0A
no final, use emprintf
vez deecho
.Acho mais legível em python:
o triplo 'garante que aspas simples em valor não sejam prejudiciais. O urllib está na biblioteca padrão. Ele funciona, por exemplo, para este URL louco (do mundo real):
fonte
encoded_value=$(python3 -c "import urllib.parse; print (urllib.parse.quote('''$value'''))")
.python -c 'import urllib, sys; sys.stdout.writelines(urllib.quote_plus(l, safe="/\n") for l in sys.stdin)'
tem quase nenhum citando problemas, e deve haver memória / velocidade eficiente (não tenho verificado, para salvar estrabismo)sys.argv
invés de substituir$value
por uma string posteriormente analisada como código. E sevalue
contido''' + __import__("os").system("rm -rf ~") + '''
?python -c "import urllib;print urllib.quote(raw_input())" <<< "$data"
Eu achei o seguinte trecho útil para colá-lo em uma cadeia de chamadas de programa, em que o URI :: Escape pode não estar instalado:
( fonte )
fonte
perl -pe 's/\%(\w\w)/chr hex $1/ge'
(fonte: unix.stackexchange.com/questions/159253/… )perl -pe 's/(\W)/sprintf("%%%02X", ord($1))/ge'
permitir letras, números e sublinhados, mas codifica todo o resto.Se você deseja executar a
GET
solicitação e usar o curl puro, adicione--get
a solução do @ Jacob.Aqui está um exemplo:
fonte
Link direto para a versão do awk: http://www.shelldorado.com/scripts/cmds/urlencode
Eu usei por anos e funciona como um encanto
fonte
Este pode ser o melhor:
fonte
after=$(echo -e ...
od
comando não é comum.od
porque usa um formato de saída diferente do GNUod
. Por exemplo,printf aa|od -An -tx1 -v|tr \ -
imprime-----------61--61--------------------------------------------------------
com o OS Xod
e-61-61
com o GNUod
. Você pode usarod -An -tx1 -v|sed 's/ */ /g;s/ *$//'|tr \ %|tr -d \\n
com o OS Xod
ou o GNUod
.xxd -p|sed 's/../%&/g'|tr -d \\n
faz a mesma coisa, mesmo quexxd
não esteja no POSIX, masod
está.Aqui está uma solução Bash que não chama nenhum programa externo:
fonte
á
isso codificará a string dentro de $ 1 e a produzirá em $ url. embora você não precise colocá-lo em um var, se quiser. BTW não incluiu o sed para tab pensei que iria transformá-lo em espaços
fonte
Usando php de um script de shell:
fonte
Para aqueles que procuram uma solução que não precisa de perl, aqui está uma que precisa apenas de hexdump e awk:
Costurados em vários lugares da rede e algumas tentativas e erros locais. Funciona muito bem!
fonte
O uni2ascii é muito útil:
fonte
%
e no espaço (essa última pode ser remediado com a-s
bandeira)Se você não quer depender do Perl, também pode usar o sed. É um pouco confuso, pois cada personagem precisa ser escapado individualmente. Crie um arquivo com o seguinte conteúdo e chame-o
urlencode.sed
Para usá-lo, faça o seguinte.
Isso dividirá a sequência em uma parte que precisa de codificação, e a parte que é boa, codifica a parte que precisa dela e, em seguida, é costurada novamente.
Você pode colocar isso em um script sh por conveniência, talvez precise de um parâmetro para codificar, coloque-o no seu caminho e, em seguida, basta chamar:
fonte
fonte
Você pode emular javascript
encodeURIComponent
em perl. Aqui está o comando:Você pode definir isso como um alias do bash em
.bash_profile
:Agora você pode canalizar para
encodeURIComponent
:fonte
Aqui está a versão do nó:
fonte
node
completamente. Publiquei uma solução apenas para Bash. :)node -p 'encodeURIComponent(require("fs").readFileSync(0))'
A questão é fazer isso no bash e não há necessidade de python ou perl, pois na verdade existe um único comando que faz exatamente o que você deseja - "urlencode".
Isso também é muito melhor, pois a resposta perl acima, por exemplo, não codifica todos os caracteres corretamente. Experimente com o longo traço obtido do Word e a codificação incorreta.
Observe que você precisa "gridsite-clients" instalado para fornecer este comando.
fonte
urlencode
. Qual versão você está usando?Opção PHP simples:
fonte
Ruby, para completar
fonte
Outra abordagem php:
fonte
echo
acrescentará um caractere de nova linha (hex0xa
). Para impedir isso, useecho -n
.Aqui está a minha versão do busybox ash shell para um sistema incorporado. Adotei originalmente a variante do Orwellophile:
fonte
Aqui está uma função POSIX para fazer isso:
Exemplo:
Fonte
fonte
Aqui está uma conversão de uma linha usando Lua, semelhante à resposta do blueyed, exceto com todos os caracteres não reservados da RFC 3986 deixados sem codificação (como esta resposta ):
Além disso, pode ser necessário garantir que as novas linhas da sua sequência sejam convertidas de LF para CRLF. Nesse caso, você pode inserir um
gsub("\r?\n", "\r\n")
na cadeia antes da codificação percentual.Aqui está uma variante que, no estilo não padrão de application / x-www-form-urlencoded , faz essa normalização de nova linha, além de codificar espaços como '+' em vez de '% 20' (que provavelmente poderiam ser adicionados ao arquivo Snippet Perl usando uma técnica semelhante).
fonte
Tendo o php instalado, eu uso desta maneira:
fonte
Esta é a versão ksh da resposta do orwellophile que contém as funções rawurlencode e rawurldecode (link: Como urlencode dados para o comando curl? ). Não tenho representante suficiente para postar um comentário, daí o novo post ..
fonte
O que analisaria URLs melhor que o javascript?
fonte
node -p 'encodeURIComponent(require("fs").readFileSync(0))'
echo | ...
está errado, enquantoecho -n | ...
suprime a nova linha.O seguinte é baseado na resposta do Orwellophile, mas resolve o bug multibyte mencionado nos comentários, definindo LC_ALL = C (um truque do vte.sh). Eu escrevi na forma de função adequada PROMPT_COMMAND, porque é assim que eu a uso.
fonte