example ejecutar desde consola comando bash shell curl scripting urlencode

bash - ejecutar - curl linux install



¿Cómo urlencode los datos para el comando curl? (30)

Estoy tratando de escribir un script de 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 guión básico hasta ahora:

#!/bin/bash host=${1:?''bad host''} value=$2 shift shift curl -v -d "param=${value}" http://${host}/somepath $@


¿Qué analizaría las URL mejor que javascript?

print_path_url() { local LC_ALL=C local string="$PWD" local strlen=${#string} local encoded="" local pos c o for (( pos=0 ; pos<strlen ; pos++ )); do c=${string:$pos:1} case "$c" in [-_.~a-zA-Z0-9/] ) o="${c}" ;; * ) printf -v o ''%%%02x'' "''$c" esac encoded+="${o}" done printf "/033]7;file://%s%s/007" "${HOSTNAME:-}" "${encoded}" }


Aquí está la respuesta BASH pura.

rawurlencode() { local string="${1}" local strlen=${#string} local encoded="" local pos c o for (( pos=0 ; pos<strlen ; pos++ )); do c=${string:$pos:1} case "$c" in [-_.~a-zA-Z0-9] ) o="${c}" ;; * ) printf -v o ''%%%02x'' "''$c" esac encoded+="${o}" done echo "${encoded}" # You can either set a return variable (FASTER) REPLY="${encoded}" #+or echo the result (EASIER)... or both... :p }

Puedes usarlo de dos maneras:

easier: echo http://url/q?=$( rawurlencode "$args" ) faster: rawurlencode "$args"; echo http://url/q?${REPLY}

[editado]

Aquí está la función rawurldecode () correspondiente, que, con toda modestia, es increíble.

# Returns a string in which the sequences with percent (%) signs followed by # two hex digits have been replaced with literal characters. rawurldecode() { # This is perhaps a risky gambit, but since all escape characters must be # encoded, we can replace %NN with /xNN and pass the lot to printf -b, which # will decode hex for us printf -v REPLY ''%b'' "${1//%///x}" # You can either set a return variable (FASTER) echo "${REPLY}" #+or echo the result (EASIER)... or both... :p }

Con el conjunto coincidente, ahora podemos realizar algunas pruebas simples:

$ diff rawurlencode.inc.sh / <( rawurldecode "$( rawurlencode "$( cat rawurlencode.inc.sh )" )" ) / && echo Matched Output: Matched

Y si realmente sientes que necesitas una herramienta externa (bueno, irá mucho más rápido y podría hacer archivos binarios y ...) Encontré esto en mi enrutador OpenWRT ...

replace_value=$(echo $replace_value | sed -f /usr/lib/ddns/url_escape.sed)

Donde url_escape.sed era un archivo que contenía estas reglas:

# sed url escaping s:%:%25:g s: :%20:g s:<:%3C:g s:>:%3E:g s:#:%23:g s:{:%7B:g s:}:%7D:g s:|:%7C:g s://:%5C:g s:/^:%5E:g s:~:%7E:g s:/[:%5B:g s:/]:%5D:g s:`:%60:g s:;:%3B:g s:/:%2F:g s:?:%3F:g s^:^%3A^g s:@:%40:g s:=:%3D:g s:&:%26:g s:/$:%24:g s:/!:%21:g s:/*:%2A:g


Aquí está la versión del nodo:

uriencode() { s="${1//''%''/%25}" s="${s//'' ''/%20}" s="${s//''"''/%22}" s="${s//''#''/%23}" s="${s//''$''/%24}" s="${s//''&''/%26}" s="${s//''+''/%2B}" s="${s//'',''/%2C}" s="${s//''/''/%2F}" s="${s//'':''/%3A}" s="${s//'';''/%3B}" s="${s//''=''/%3D}" s="${s//''?''/%3F}" s="${s//''@''/%40}" s="${s//''[''/%5B}" s="${s//'']''/%5D}" printf %s "$s" }


Aquí está mi versión para shell shell de busybox para un sistema integrado, originalmente adopté la variante de Orwellophile:

urlencode() { local S="${1}" local encoded="" local ch local o for i in $(seq 0 $((${#S} - 1)) ) do ch=${S:$i:1} case "${ch}" in [-_.~a-zA-Z0-9]) o="${ch}" ;; *) o=$(printf ''%%%02x'' "''$ch") ;; esac encoded="${encoded}${o}" done echo ${encoded} } urldecode() { # urldecode <string> local url_encoded="${1//+/ }" printf ''%b'' "${url_encoded//%///x}" }


Aquí hay una conversión de una línea que usa Lua, similar a la respuesta de blueyed, excepto que todos los caracteres sin reserva RFC 3986 quedan sin codificar (como esta respuesta ):

url=$(echo ''print((arg[1]:gsub("([^%w%-%.%_%~])",function(c)return("%%%02X"):format(c:byte())end)))'' | lua - "$1")

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 del porcentaje codificación

Aquí hay una variante que, en el estilo no estándar de application / x-www-form-urlencoded , realiza esa normalización de nueva línea, así como los espacios de codificación como ''+'' en lugar de ''% 20'' (que probablemente podrían agregarse a la Fragmento de Perl utilizando una técnica similar).

url=$(echo ''print((arg[1]:gsub("/r?/n", "/r/n"):gsub("([^%w%-%.%_%~ ]))",function(c)return("%%%02X"):format(c:byte())end):gsub(" ","+"))'' | lua - "$1")


Aquí hay una función POSIX para hacer eso:

encodeURIComponent() { awk ''BEGIN {while (y++ < 125) z[sprintf("%c", y)] = y while (y = substr(ARGV[1], ++j, 1)) q = y ~ /[[:alnum:]_.!~*/47()-]/ ? q y : q sprintf("%%%02X", z[y]) print q}'' "$1" }

Ejemplo:

value=$(encodeURIComponent "$2")

Source


Aquí hay una solución Bash que no invoca ningún programa externo:

echo "encode me" | php -r "echo urlencode(file_get_contents(''php://stdin''));"


Enlace directo a la versión awk: http://www.shelldorado.com/scripts/cmds/urlencode
Lo utilicé durante años y funciona a la perfección.

: ########################################################################## # Title : urlencode - encode URL data # Author : Heiner Steven ([email protected]) # Date : 2000-03-15 # Requires : awk # Categories : File Conversion, WWW, CGI # SCCS-Id. : @(#) urlencode 1.4 06/10/29 ########################################################################## # Description # Encode data according to # RFC 1738: "Uniform Resource Locators (URL)" and # RFC 1866: "Hypertext Markup Language - 2.0" (HTML) # # This encoding is used i.e. for the MIME type # "application/x-www-form-urlencoded" # # Notes # o The default behaviour is not to encode the line endings. This # may not be what was intended, because the result will be # multiple lines of output (which cannot be used in an URL or a # HTTP "POST" request). If the desired output should be one # line, use the "-l" option. # # o The "-l" option assumes, that the end-of-line is denoted by # the character LF (ASCII 10). This is not true for Windows or # Mac systems, where the end of a line is denoted by the two # characters CR LF (ASCII 13 10). # We use this for symmetry; data processed in the following way: # cat | urlencode -l | urldecode -l # should (and will) result in the original data # # o Large lines (or binary files) will break many AWK # implementations. If you get the message # awk: record `...'' too long # record number xxx # consider using GNU AWK (gawk). # # o urlencode will always terminate it''s output with an EOL # character # # Thanks to Stefan Brozinski for pointing out a bug related to non-standard # locales. # # See also # urldecode ########################################################################## PN=`basename "$0"` # Program name VER=''1.4'' : ${AWK=awk} Usage () { echo >&2 "$PN - encode URL data, $VER usage: $PN [-l] [file ...] -l: encode line endings (result will be one line of output) The default is to encode each input line on its own." exit 1 } Msg () { for MsgLine do echo "$PN: $MsgLine" >&2 done } Fatal () { Msg "$@"; exit 1; } set -- `getopt hl "$@" 2>/dev/null` || Usage [ $# -lt 1 ] && Usage # "getopt" detected an error EncodeEOL=no while [ $# -gt 0 ] do case "$1" in -l) EncodeEOL=yes;; --) shift; break;; -h) Usage;; -*) Usage;; *) break;; # First file name esac shift done LANG=C export LANG $AWK '' BEGIN { # We assume an awk implementation that is just plain dumb. # We will convert an character to its ASCII value with the # table ord[], and produce two-digit hexadecimal output # without the printf("%02X") feature. EOL = "%0A" # "end of line" string (encoded) split ("1 2 3 4 5 6 7 8 9 A B C D E F", hextab, " ") hextab [0] = 0 for ( i=1; i<=255; ++i ) ord [ sprintf ("%c", i) "" ] = i + 0 if ("''"$EncodeEOL"''" == "yes") EncodeEOL = 1; else EncodeEOL = 0 } { encoded = "" for ( i=1; i<=length ($0); ++i ) { c = substr ($0, i, 1) if ( c ~ /[a-zA-Z0-9.-]/ ) { encoded = encoded c # safe character } else if ( c == " " ) { encoded = encoded "+" # special handling } else { # unsafe character, encode it as a two-digit hex-number lo = ord [c] % 16 hi = int (ord [c] / 16); encoded = encoded "%" hextab [hi] hextab [lo] } } if ( EncodeEOL ) { printf ("%s", encoded EOL) } else { print encoded } } END { #if ( EncodeEOL ) print "" } '' "$@"


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 ..

#!/bin/ksh93 function rawurlencode { typeset string="${1}" typeset strlen=${#string} typeset encoded="" for (( pos=0 ; pos<strlen ; pos++ )); do c=${string:$pos:1} case "$c" in [-_.~a-zA-Z0-9] ) o="${c}" ;; * ) o=$(printf ''%%%02x'' "''$c") esac encoded+="${o}" done print "${encoded}" } function rawurldecode { printf $(printf ''%b'' "${1//%///x}") } print $(rawurlencode "C++") # --> C%2b%2b print $(rawurldecode "C%2b%2b") # --> C++


Este puede ser el mejor:

after=$(echo -e "$before" | od -An -tx1 | tr '' '' % | xargs printf "%s")


Habiendo instalado php lo uso de esta manera:

URL_ENCODED_DATA=`php -r "echo urlencode(''$DATA'');"`


He encontrado el siguiente fragmento de código útil para integrarlo en una cadena de llamadas a programas, donde URI :: Escape podría no estar instalado:

perl -p -e ''s/([^A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg''

( source )


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 usted quiere: "urlencode".

value=$(urlencode "${2}")

Esto también es mucho mejor, ya que la respuesta perl anterior, por ejemplo, no codifica todos los caracteres correctamente. Inténtalo con el guión largo que obtienes de Word y obtienes la codificación incorrecta.

Tenga en cuenta que necesita "gridsite-clients" instalados para proporcionar este comando.


Lo encuentro más legible en python:

encoded_value=$(python -c "import urllib; print urllib.quote(''''''$value'''''')")

el triple ''asegura que las comillas simples en valor no duelen. urllib está en la biblioteca estándar. Funciona por ejemplo para esta loca (mundo real) url:

"http://www.rai.it/dl/audio/" "1264165523944Ho servito il re d''Inghilterra - Puntata 7


Lo siguiente se basa en la respuesta de Orwellophile, pero resuelve el error multibyte mencionado en los comentarios al establecer LC_ALL = C (un truco de vte.sh). Lo he escrito en la forma de función adecuada PROMPT_COMMAND, porque así es como lo uso.

node -p "encodeURIComponent(''$url'')"


Opción simple de PHP:

echo ''part-that-needs-encoding'' | php -R ''echo urlencode($argn);''


Otra opción es usar jq :

jq -s -R -r @uri

-s ( --slurp ) lee las líneas de entrada en una matriz y -s -R ( --slurp --raw-input ) lee la entrada en una sola cadena. -r ( --raw-output ) genera el contenido de las cadenas en lugar de los literales de cadena JSON.

O este porcentaje codifica todos los bytes:

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


Otro enfoque php:

uriencode() { node -p "encodeURIComponent(''${1///'////'}'')" }


Para aquellos de ustedes que buscan una solución que no necesita perl, aquí hay una que solo necesita hexdump y awk:

url_encode() { [ $# -lt 1 ] && { return; } encodedurl="$1"; # make sure hexdump exists, if not, just give back the url [ ! -x "/usr/bin/hexdump" ] && { return; } encodedurl=` echo $encodedurl | hexdump -v -e ''1/1 "%02x/t"'' -e ''1/1 "%_c/n"'' | LANG=C awk '' $1 == "20" { printf("%s", "+"); next } # space becomes plus $1 ~ /0[adAD]/ { next } # strip newlines $2 ~ /^[a-zA-Z0-9.*()//-]$/ { printf("%s", $2); next } # pass through what we can { printf("%%%s", $1) } # take hex value of everything else ''` }

Unidas desde un par de lugares a través de la red y algunos ensayos y errores locales. Funciona muy bien


Puede emular el encodeURIComponent de javascript en perl. Aquí está el comando:

perl -pe ''s/([^a-zA-Z0-9_.!~*()''/'''-])/sprintf("%%%02X", ord($1))/ge''

Podría establecer esto como un alias de bash en .bash_profile :

alias encodeURIComponent=''perl -pe ''/'''s/([^a-zA-Z0-9_.!~*()''/'''/'/'''''/'''-])/sprintf("%%%02X",ord($1))/ge''/'

Ahora puedes canalizar en encodeURIComponent :

$ echo -n ''hèllo wôrld!'' | encodeURIComponent h%C3%A8llo%20w%C3%B4rld!


Ruby, para completar

value="$(ruby -r cgi -e ''puts CGI.escape(ARGV[0])'' "$2")"


Si desea ejecutar la solicitud GET y usar el enrollamiento puro, simplemente agregue --get a la solución de --get .

Aquí hay un ejemplo:

curl -v --get --data-urlencode "access_token=$(cat .fb_access_token)" https://graph.facebook.com/me/feed


Si no quieres depender de Perl, también puedes usar sed. Es un poco desordenado, ya que cada personaje debe ser escapado individualmente. Crea un archivo con el siguiente contenido y llámalo urlencode.sed

s/%/%25/g s/ /%20/g s/ /%09/g s/!/%21/g s/"/%22/g s/#/%23/g s//$/%24/g s//&/%26/g s/''/'''/%27/g s/(/%28/g s/)/%29/g s//*/%2a/g s/+/%2b/g s/,/%2c/g s/-/%2d/g s//./%2e/g s////%2f/g s/:/%3a/g s/;/%3b/g s//%3e/g s/?/%3f/g s/@/%40/g s//[/%5b/g s////%5c/g s//]/%5d/g s//^/%5e/g s/_/%5f/g s/`/%60/g s/{/%7b/g s/|/%7c/g s/}/%7d/g s/~/%7e/g s/ /%09/g

Para usarlo haz lo siguiente.

STR1=$(echo "https://www.example.com/change&$ ^this to?%checkthe@-functionality" | cut -d/? -f1) STR2=$(echo "https://www.example.com/change&$ ^this to?%checkthe@-functionality" | cut -d/? -f2) OUT2=$(echo "$STR2" | sed -f urlencode.sed) echo "$STR1?$OUT2"

Esto dividirá la cadena en una parte que necesita codificación, y la parte que está bien, codificará la parte que la necesita, y luego vuelve a unir.

Puede poner eso en una secuencia de comandos sh para mayor comodidad, tal vez pedirle que tome un parámetro para codificar, ponerlo en su ruta y luego simplemente puede llamar:

urlencode https://www.exxample.com?isThisFun=HellNo

source


Una de las variantes, puede ser fea, pero simple:

urlencode() { local data if [[ $# != 1 ]]; then echo "Usage: $0 string-to-urlencode" return 1 fi data="$(curl -s -o /dev/null -w %{url_effective} --get --data-urlencode "$1" "")" if [[ $? != 3 ]]; then echo "Unexpected error" 1>&2 return 2 fi echo "${data##/?}" return 0 }

Aquí está la versión de una sola línea, por ejemplo (como lo sugiere Bruno ):

date | curl -Gso /dev/null -w %{url_effective} --data-urlencode @- "" | cut -c 3-



Use el módulo URI::Escape Perl y la función uri_escape en la segunda línea de su script de bash:

... value="$(perl -MURI::Escape -e ''print uri_escape($ARGV[0]);'' "$2")" ...

Edición: Solucione los problemas de cotización, como lo sugirió Chris Johnsen en los comentarios. ¡Gracias!


Utilice curl --data-urlencode ; del man curl :

Esto publica datos, de forma similar a las otras opciones de --data , con la excepción de que realiza la codificación de URL. Para ser compatible con CGI, la parte <data> debe comenzar con un nombre seguido de un separador y una especificación de contenido.

Ejemplo de uso:

curl / --data-urlencode "paramName=value" / --data-urlencode "secondParam=value" / http://example.com

Vea la página del manual para más información.

Esto requiere curl 7.18.0 o más reciente (publicado en enero de 2008) . Utilice curl -V para comprobar qué versión tiene.


para completar, muchas soluciones que usan sed o awk 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 codificar cada byte, incluso aquellos que se hubieran permitido.

echo -ne ''some random/nbytes'' | xxd -plain | tr -d ''/n'' | sed ''s//(../)/%/1/g''

xxd se ocupa de que la entrada se maneje como bytes y no como caracteres.

editar:

xxd viene con el paquete vim-common en Debian y estaba en un sistema donde no estaba instalado y no quería instalarlo. La alternativa es usar hexdump del paquete bsdmainutils en Debian. De acuerdo con el siguiente gráfico, bsdmainutils y vim-common deberían tener aproximadamente 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 hexdump lugar de xxd y permite evitar la llamada tr :

echo -ne ''some random/nbytes'' | hexdump -v -e ''/1 "%02x"'' | sed ''s//(../)/%/1/g''


uni2ascii es muy útil:

$ echo -ne ''你好世界'' | uni2ascii -aJ %E4%BD%A0%E5%A5%BD%E4%B8%96%E7%95%8C


url=$(echo "$1" | sed -e ''s/%/%25/g'' -e ''s/ /%20/g'' -e ''s/!/%21/g'' -e ''s/"/%22/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'' -e ''s//*/%2a/g'' -e ''s/+/%2b/g'' -e ''s/,/%2c/g'' -e ''s/-/%2d/g'' -e ''s//./%2e/g'' -e ''s////%2f/g'' -e ''s/:/%3a/g'' -e ''s/;/%3b/g'' -e ''s//%3e/g'' -e ''s/?/%3f/g'' -e ''s/@/%40/g'' -e ''s//[/%5b/g'' -e ''s////%5c/g'' -e ''s//]/%5d/g'' -e ''s//^/%5e/g'' -e ''s/_/%5f/g'' -e ''s/`/%60/g'' -e ''s/{/%7b/g'' -e ''s/|/%7c/g'' -e ''s/}/%7d/g'' -e ''s/~/%7e/g'')

esto codificará la cadena dentro de $ 1 y la generará en $ url. aunque no tienes que ponerlo en una var si quieres. BTW no incluyó el sed para la pestaña, pensó que lo convertiría en espacios