How to urlencode data for curl command? How to urlencode data for curl command? bash bash

How to urlencode data for curl command?


Use curl --data-urlencode; from man curl:

This posts data, similar to the other --data options with the exception that this performs URL-encoding. To be CGI-compliant, the <data> part should begin with a name followed by a separator and a content specification.

Example usage:

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

See the man page for more info.

This requires curl 7.18.0 or newer (released January 2008). Use curl -V to check which version you have.

You can as well encode the query string:

curl -G \    --data-urlencode "p1=value 1" \    --data-urlencode "p2=value 2" \    http://example.com    # http://example.com?p1=value%201&p2=value%202


Here is the pure BASH answer.

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}

You can use it in two ways:

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

[edited]

Here's the matching rawurldecode() function, which - with all modesty - is awesome.

# 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}

With the matching set, we can now perform some simple tests:

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

And if you really really feel that you need an external tool (well, it will go a lot faster, and might do binary files and such...) I found this on my OpenWRT router...

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

Where url_escape.sed was a file that contained these rules:

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


Another option is to use jq:

$ printf %s 'encode this'|jq -sRr @uriencode%20this$ jq -rn --arg x 'encode this' '$x|@uri'encode%20this

-r (--raw-output) outputs the raw contents of strings instead of JSON string literals. -n (--null-input) doesn't read input from STDIN.

-R (--raw-input) treats input lines as strings instead of parsing them as JSON, and -sR (--slurp --raw-input) reads the input into a single string. You can replace -sRr with -Rr if your input only contains a single line, or if you don't want to replace linefeeds with %0A:

$ printf %s\\n 'multiple lines' 'of text'|jq -Rr @urimultiple%20linesof%20text$ printf %s\\n 'multiple lines' 'of text'|jq -sRr @urimultiple%20lines%0Aof%20text%0A

Or this percent-encodes all bytes:

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