Associative array from querystring in bash?
-
21-12-2019 - |
Question
How do I get an associative array from a query string in Bash? - Attempt:
#!/usr/bin/env bash
# Querystring (implementation stolen from http://stackoverflow.com/q/3919755)
function populate_querystring_array ()
{
param="$1"
query_dict="$2"
#for i in "${array[@]}"; do IFS="=" ; set -- $i; query_dict[$1]=$2; done
for ((i=0; i<${#param[@]}; i+=2))
do
query_dict[${param[i]}]=${param[i+1]}
done
}
q0='email=foo@bar.com&password=dfsa54'
declare -A querydict
populate_querystring_array "$q0" "$querydict"
printf "$querydict[email]"
Solution
Below should work:
#!/bin/bash
function qrystring() {
qry=$1
while read key value; do
arr+=(["$key"]="$value")
done < <(awk -F'&' '{for(i=1;i<=NF;i++) {print $i}}' <<< $qry | awk -F'=' '{print $1" "$2}')
}
q='email=foo@bar.com&password=dfsa54'
declare -A arr
qrystring "$q"
for k in ${!arr[@]}; do
echo "$k -> ${arr[$k]}"
done
Explanation:
Im using a combination of awk commands to split the string into individual records first, then split on the = sign for kv pair.
I'm using process substitution here otherwise i would be populating a copy of the array.
EDIT:
Using a global variable to house array.
OTHER TIPS
#!/usr/bin/env bash
q0='email=foo@bar.com&password=dfsa54'
declare -A querydict
while IFS== read key value
do
querydict["$key"]="$value"
done < <(echo "$q0" | sed 's/&/\n/g' )
printf "${querydict[email]}\n"
In the above, 's/&/\n/g'
is a sed
command that replaces every occurrence of &
with a new line. We apply this to q0
so that every parameter assignment is on a separate line. The parameter assignments are then read into the while
loop. To read each assignment, IFS== read key value
is used. IFS==
tells read
to treat the equal sign as a word separator. Thus, each assignment is broken into two words: the first is the key and the second is the value. These are then assigned to the associative array querydict
with the statement querydict["$key"]="$value"
.
Putting it in a function
bash
differs from most modern programming languages in that its facilities for passing complex data into and out of functions are extremely limited. In the method shown below, the associative array, querydict
, is a global variable:
#!/usr/bin/env bash
declare -A querydict
populate_querystring_array () {
query="$1"
while IFS== read arg value
do
querydict["$arg"]="$value"
done < <(echo "$query" | sed 's/&/\n/g' )
}
q0='email=foo@bar.com&password=dfsa54'
populate_querystring_array "$q0"
printf "${querydict[email]}\n"
Taking @John1024's answer I use it in a function which returns the associative array by value, simply printing out the contents using array syntax:
function parseQuery {
local querystring="$*"
echo -n "("
echo "${querystring}" | sed 's/&/\n/g' | while IFS== read arg value
do
echo -n "[${arg}]='${value}' "
done
echo ")"
}
declare -A querydict=$(parseQuery "${QUERY_STRING}" )