Estoy tratando de escribir un script bash para la prueba que toma un parámetro y lo envía a través de curl al sitio web. Necesito url codificar el valor para asegurarme de que los caracteres especiales se procesen correctamente. ¿Cuál es la mejor manera de hacer esto?
Aquí está mi script básico hasta ahora:
#!/bin/bash
host=${1:?'bad host'}
value=$2
shift
shift
curl -v -d "param=${value}" http://${host}/somepath $@
Respuestas:
Uso
curl --data-urlencode
; deman curl
:Ejemplo de uso:
Vea la página del manual para más información.
Esto requiere curl 7.18.0 o posterior (lanzado en enero de 2008) . Use
curl -V
para verificar qué versión tiene.También puede codificar la cadena de consulta :
fuente
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
. ¿Alguna idea de por qué? `"
the‽Aquí está la respuesta BASH pura.
Puedes usarlo de dos maneras:
[editado]
Aquí está la función rawurldecode (), que, con toda modestia, es increíble.
Con el conjunto correspondiente, ahora podemos realizar algunas pruebas simples:
Y si realmente siente que necesita una herramienta externa (bueno, irá mucho más rápido y podría hacer archivos binarios y tal ...) Encontré esto en mi enrutador OpenWRT ...
Donde url_escape.sed era un archivo que contenía estas reglas:
fuente
Jogging «à l'Hèze»
generaJogging%20%abà%20l%27Hèze%bb
que no se puede alimentar a JSdecodeURIComponent
:(\u0144
), generará ingenuamente% 144, ╡ (\u2561
) se generará como% 2561. Las respuestas correctas sin codificar para estas serían% C5% 84% 0A y% E2% 95% A1 respectivamente.Use el
URI::Escape
módulo y lauri_escape
función de Perl en la segunda línea de su script bash:Editar: Solucione problemas de citas, como lo sugiere Chris Johnsen en los comentarios. ¡Gracias!
fuente
echo
, pipe y<>
), y ahora funciona incluso cuando $ 2 contiene un apóstrofe o comillas dobles. ¡Gracias!echo
:value="$(perl -MURI::Escape -e 'print uri_escape($ARGV[0]);' "$2")"
Otra opción es usar
jq
(como filtro):-R
(--raw-input
) trata las líneas de entrada como cadenas en lugar de analizarlas como JSON y-sR
(--slurp --raw-input
) lee la entrada en una sola cadena.-r
(--raw-output
) genera el contenido de cadenas en lugar de literales de cadena JSON.Si la entrada no es la salida de otro comando, puede almacenarlo en una
jq
variable de cadena:-n
(--null-input
) no lee la entrada, y--arg name value
almacenavalue
en variablename
como una cadena. En el filtro,$name
(entre comillas simples, para evitar la expansión por el shell), hace referencia a la variablename
.Envuelto como una función Bash, esto se convierte en:
O este porcentaje codifica todos los bytes:
fuente
curl
que codifique eso funciona y si bash tiene un valor incorporado que hubiera sido aceptable, perojq
parece un ajuste adecuado, aunque estoy lejos de alcanzar el nivel de comodidad con esta herramienta)@uri
no es una variable, sino un filtro jq literal usado para formatear cadenas y escapar; consulte el manual de jq para obtener más detalles (lo siento, no hay un enlace directo, es necesario buscar@uri
en la página ...)printf "http://localhost:8082/" | jq -sRr '@uri'
en aras de la integridad, muchas soluciones que utilizan
sed
oawk
solo traducen un conjunto especial de caracteres y, por lo tanto, son bastante grandes por tamaño de código y tampoco traducen otros caracteres especiales que deben codificarse.Una forma segura de urlencode sería simplemente codificar cada byte, incluso aquellos que se habrían permitido.
xxd se encarga aquí de que la entrada se maneje como bytes y no como caracteres.
editar:
xxd viene con el paquete vim-common en Debian y solo estaba en un sistema donde no estaba instalado y no quería instalarlo. La alternativa es usar
hexdump
desde el paquete bsdmainutils en Debian. De acuerdo con el siguiente gráfico, bsdmainutils y vim-common deberían tener la misma probabilidad de ser instalados:http://qa.debian.org/popcon-png.php?packages=vim-common%2Cbsdmainutils&show_installed=1&want_legend=1&want_ticks=1
pero, sin embargo, aquí hay una versión que usa en
hexdump
lugar dexxd
y permite evitar latr
llamada:fuente
xxd -plain
debe suceder DESPUÉStr -d '\n'
!\n
carácter será traducido porxxd -plain
a0a
. No confíes en mi palabra, pruébalo tú mismo:echo -n -e '\n' | xxd -plain
esto demuestra que tutr -d '\n'
es inútil aquí, ya que no puede haber\n
después dexxd -plain
Second,echo foobar
agrega su propio\n
carácter al final de la cadena de caracteres, porxxd -plain
lo que no se alimenta confoobar
lo esperado sino confoobar\n
. luego loxxd -plain
traduce en una cadena de caracteres que termina en0a
, haciéndolo inadecuado para el usuario. Podrías agregar-n
aecho
para resolverlo.xxd
llamada pertenece al frente de latr -d
llamada. Pertenece allí para que cualquier nueva línea enfoobar
sea traducida porxxd
. Eltr -d
después de laxxd
llamada es eliminar las nuevas líneas que xxd produce. Parece que nunca tiene foobar el tiempo suficiente para quexxd
produzca nuevas líneas, pero para entradas largas lo hará. Entonces eltr -d
es necesario. En contraste con su suposición,tr -d
NO era eliminar las nuevas líneas de la entrada, sino de laxxd
salida. Quiero mantener las nuevas líneas en la entrada. Su único punto válido es que ese eco agrega una nueva línea innecesaria.echo -n
que realmente me faltabaUna de las variantes, puede ser fea, pero simple:
Aquí está la versión de una línea, por ejemplo (como lo sugirió Bruno ):
fuente
date
comando ...date | curl -Gso /dev/null -w %{url_effective} --data-urlencode @- "" | cut -c 3-
(cut
Debe quitar los primeros 2 caracteres, porque la salida de curl es técnicamente una URL relativa con una cadena de consulta).%0A
al final, use enprintf
lugar deecho
.Lo encuentro más legible en Python:
el triple 'asegura que las comillas simples en valor no duelen. urllib está en la biblioteca estándar. Funciona por ejemplo para esta loca url (mundo real):
fuente
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)'
casi no tiene problemas de cotización, y debe ser eficiente en cuanto a memoria / velocidad (no lo he verificado, salvo por entrecerrar los ojos)sys.argv
lugar de sustituirlo$value
en una cadena que luego se analizó como código. ¿Qué pasa si estávalue
contenido''' + __import__("os").system("rm -rf ~") + '''
?python -c "import urllib;print urllib.quote(raw_input())" <<< "$data"
He encontrado el siguiente fragmento útil para pegarlo en una cadena de llamadas de programa, donde URI :: Escape podría no estar instalado:
( fuente )
fuente
perl -pe 's/\%(\w\w)/chr hex $1/ge'
(fuente: unix.stackexchange.com/questions/159253/… )perl -pe 's/(\W)/sprintf("%%%02X", ord($1))/ge'
permitir letras, números y guiones bajos, pero codifica todo lo demás.Si desea ejecutar la
GET
solicitud y usar curl puro, simplemente agregue--get
a la solución de @ Jacob.Aquí hay un ejemplo:
fuente
Enlace directo a la versión awk: http://www.shelldorado.com/scripts/cmds/urlencode
Lo utilicé durante años y funciona de maravilla
fuente
Este puede ser el mejor:
fuente
after=$(echo -e ...
od
comando no es común.od
porque usa un formato de salida diferente al de GNUod
. Por ejemplo,printf aa|od -An -tx1 -v|tr \ -
imprime-----------61--61--------------------------------------------------------
con OS Xod
y-61-61
con GNUod
. Puede usarlood -An -tx1 -v|sed 's/ */ /g;s/ *$//'|tr \ %|tr -d \\n
con OS Xod
o GNUod
.xxd -p|sed 's/../%&/g'|tr -d \\n
hace lo mismo, aunquexxd
no está en POSIX pero síod
.Aquí hay una solución Bash que no invoca ningún programa externo:
fuente
á
esto codificará la cadena dentro de $ 1 y la generará en $ url. aunque no tienes que ponerlo en una var si quieres. Por cierto, no incluyó el sed para tab pensó que lo convertiría en espacios
fuente
Usando php desde un script de shell:
fuente
Para aquellos de ustedes que buscan una solución que no necesita perl, aquí hay una que solo necesita hexdump y awk:
Unidas desde un par de lugares en la red y algunas pruebas y errores locales. ¡Funciona muy bien!
fuente
uni2ascii es muy útil:
fuente
%
y espacio (lo último puede remediarse con la-s
bandera)Si no desea depender de Perl, también puede usar sed. Es un poco desordenado, ya que cada personaje tiene que escapar individualmente. Haga un archivo con los siguientes contenidos y llámelo
urlencode.sed
Para usarlo haga lo siguiente.
Esto dividirá la cadena en una parte que necesita codificación, y la parte que está bien, codifica la parte que la necesita, luego vuelve a unirlas.
Puede poner eso en un script sh por conveniencia, tal vez hacer que tome un parámetro para codificar, ponerlo en su ruta y luego simplemente puede llamar:
fuente
fuente
Puede emular javascript
encodeURIComponent
en perl. Aquí está el comando:Puede establecer esto como un alias bash en
.bash_profile
:Ahora puedes conectarlo a
encodeURIComponent
:fuente
Aquí está la versión del nodo:
fuente
node
completo. Publiqué una solución solo para Bash. :)node -p 'encodeURIComponent(require("fs").readFileSync(0))'
La pregunta es sobre hacer esto en bash y no hay necesidad de python o perl ya que de hecho hay un solo comando que hace exactamente lo que quieres: "urlencode".
Esto también es mucho mejor, ya que la respuesta perl anterior, por ejemplo, no codifica todos los caracteres correctamente. Pruébelo con el guión largo que obtiene de Word y obtiene la codificación incorrecta.
Tenga en cuenta que necesita instalar "gridsite-clients" para proporcionar este comando.
fuente
urlencode
. Qué versión estás usando?Opción PHP simple:
fuente
Ruby, para completar
fuente
Otro enfoque de php:
fuente
echo
agregará un carácter de nueva línea (hexadecimal0xa
). Para evitar que haga eso, useecho -n
.Aquí está mi versión para busybox ash shell para un sistema embebido, originalmente adopté la variante de Orwellophile:
fuente
Aquí hay una función POSIX para hacer eso:
Ejemplo:
Fuente
fuente
Aquí hay una conversión de una línea usando Lua, similar a la respuesta de blueyed, excepto con todos los caracteres no reservados RFC 3986 sin codificar (como esta respuesta ):
Además, es posible que deba asegurarse de que las nuevas líneas en su cadena se conviertan de LF a CRLF, en cuyo caso puede insertar un
gsub("\r?\n", "\r\n")
en la cadena antes de la codificación porcentual.Aquí hay una variante que, en el estilo no estándar de aplicación / x-www-form-urlencoded , realiza esa normalización de nueva línea, así como codifica espacios como '+' en lugar de '% 20' (que probablemente podría agregarse al Fragmento de Perl usando una técnica similar).
fuente
Habiendo instalado php, lo uso de esta manera:
fuente
Esta es la versión ksh de la respuesta de orwellophile que contiene las funciones rawurlencode y rawurldecode (enlace: ¿Cómo urlencode datos para el comando curl? ). No tengo suficiente representante para publicar un comentario, de ahí la nueva publicación ...
fuente
¿Qué analizaría mejor las URL que JavaScript?
fuente
node -p 'encodeURIComponent(require("fs").readFileSync(0))'
echo | ...
está mal, mientras queecho -n | ...
suprime la nueva línea.Lo siguiente se basa en la respuesta de Orwellophile, pero resuelve el error multibyte mencionado en los comentarios configurando LC_ALL = C (un truco de vte.sh). Lo escribí en forma de función adecuada PROMPT_COMMAND, porque así es como lo uso.
fuente