I have a bash script that is being used in a CGI. The CGI sets the $QUERY_STRING environment variable by reading everything after the ?
in the URL. For example, http://example.com?a=123&b=456&c=ok sets QUERY_STRING=a=123&b=456&c=ok
.
Somewhere I found the following ugliness:
b=$(echo "$QUERY_STRING" | sed -n 's/^.*b=\([^&]*\).*$/\1/p' | sed "s/%20/ /g")
which will set $b to whatever was found in $QUERY_STRING for b
. However, my script has grown to have over ten input parameters. Is there an easier way to automatically convert the parameters in $QUERY_STRING into environment variables usable by bash?
Maybe I'll just use a for loop of some sort, but it'd be even better if the script was smart enough to automatically detect each parameter and maybe build an array that looks something like this:
${parm[a]}=123 ${parm[b]}=456 ${parm[c]}=ok
How could I write code to do that?
why not this
now you have this
you can break
$QUERY
down usingIFS
. For example, setting it to&
And you can save to a hash/dictionary in Bash 4+
I packaged the sed command up into another script:
$cat getvar.sh
and I call it from my main cgi as:
...etc, etc - you get idea.
works for me even with a very basic busybox appliance (my PVR in this case).
To bring this up to date, if you have a recent Bash version then you can achieve this with regular expressions:
If you don't want to use associative arrays then just change the penultimate line to do what you want. For each iteration of the loop the parameter is in
${BASH_REMATCH[1]}
and its value is in${BASH_REMATCH[2]}
.Here is the same thing as a function in a short test script that iterates over the array outputs the query string's parameters and their values
Note the parameters end up in the array in reverse order (it's associative so that shouldn't matter).
For all those who couldn't get it working with the posted answers (like me), this guy figured it out.
Can't upvote his post unfortunately...
Let me repost the code here real quick:
Hope this is of help for anybody.
Cheers
While the accepted answer is probably the most beautiful one, there might be cases where security is super-important, and it needs to be also well-visible from your script.
In such a case, first I wouldn't use bash for the task, but if it should be done on some reason, it might be better to avoid these new array - dictionary features, because you can't be sure, how exactly are they escaped.
In this case, the good old primitive solutions might work:
This iterates on the name-value pairs of the
QUERY_STRING
, and there is no way to circumvent it with any tricky escape sequence - the"
is a very strong thing in bash, except a single variable name substitution, which is fully controlled by us, nothing can be tricked.Furthermore, you can inject your own processing code into "
# ...
". This enables you to allow only your own, well-defined (and, ideally, short) list of the allowed variable names. Needless to say,LD_PRELOAD
shouldn't be one of them. ;-)Furthermore, no variable will be exported, and exclusively
QS
,nameval
,name
andval
is used.