return as environment variable
Opened this issue · 5 comments
i use JSON.sh as curl 'http://conf.com/conf/config_20150920_test.json' | ./JSON.sh -l -p -b -s
and it work greet and it return result like
["storage","mysql","u_db","database"] "dev"
["storage","mysql","u_db","username"] "user"
["storage","mysql","u_db","password"] "123@1"
["storage","mysql","u_db","internal_ip"] "10.176.192.120"
["storage","mysql","u_db","internal_port"] 3306
["storage","mysql","a","database"] "a"
["storage","mysql","a","username"] "user"
["storage","mysql","a","password"] "122a@1"
but what if add config param to determine how output look like and go with exporting this variables as env variables like
storage_mysql_u_db_internal_port=3306
storage_mysql_a_database=a
storage_mysql_a_username=user
storage_mysql_a_password=122a@1
which make it easy to be evaluated with eval
as environment variable.
Not exactly what you're asking for, but I use the following two functions for extracting values from the JSON.sh output:
#function to get value of specified key
#returns empty string if not found
#warning - does not validate key format (supplied as parameter) in any way, simply returns empty string for malformed queries too
#usage: VAR=$(getkey foo.bar) #get value of "bar" contained within "foo"
# VAR=$(getkey foo[4].bar) #get value of "bar" contained in the array "foo" on position 4
# VAR=$(getkey [4].foo) #get value of "foo" contained in the root unnamed array on position 4
function getkey {
#reformat key string (parameter) to what JSON.sh uses
KEYSTRING=$(sed -e 's/\[/\"\,/g' -e 's/^\"\,/\[/g' -e 's/\]\./\,\"/g' -e 's/\./\"\,\"/g' -e '/^\[/! s/^/\[\"/g' -e '/\]$/! s/$/\"\]/g' <<< "$@")
#extract the key value
FOUT=$(grep -F "$KEYSTRING" <<< "$JSON_PARSED")
FOUT="${FOUT#*$'\t'}"
FOUT="${FOUT#*\"}"
FOUT="${FOUT%\"*}"
echo "$FOUT"
}
#function returning length of array
#returns zero if key in parameter does not exist or is not an array
#usage: VAR=$(getarrlen foo.bar) #get length of array "bar" contained within "foo"
# VAR=$(getarrlen) #get length of the root unnamed array
# VAR=$(getarrlen [2].foo.bar) #get length of array "bar" contained within "foo", which is stored in the root unnamed array on position 2
function getarrlen {
#reformat key string (parameter) to what JSON.sh uses
KEYSTRING=$(sed -e '/^\[/! s/\[/\"\,/g' -e 's/\]\./\,\"/g' -e 's/\./\"\,\"/g' -e '/^$/! {/^\[/! s/^/\[\"/g}' -e '/^$/! s/$/\"\,/g' -e 's/\[/\\\[/g' -e 's/\]/\\\]/g' -e 's/\,/\\\,/g' -e '/^$/ s/^/\\\[/g' <<< "$@")
#extract the key array length - get last index
LEN=$(grep -o "${KEYSTRING}[0-9]*" <<< "$JSON_PARSED" | tail -n -1 | grep -o "[0-9]*$")
#increment to get length, if empty => zero
if [ -n "$LEN" ]; then
LEN=$(($LEN+1))
else
LEN="0"
fi
echo "$LEN"
}
It expects the JSON.sh to be run with the -l
flag and output stored in the variable $JSON_PARSED
.
Also, using eval
as you suggested can be dangerous if the output is improperly escaped. For example, string "; rm -rf /"
in the JSON data could lead to disaster.
So how about adding these to JSON.sh itself? That way you could source it, parse the json once and query away.
Also, how would you get a list of keys in an object?
Depends on the format you'd like. If the subset of JSON structure is OK for you, just use it without the -l
option and specify a "path" to the object in question. In this case, my code snippet should give you this substructure.
If you really want a simple list of strings, you could re-parse this subset with JSON.sh and just extract (grep + regex) the first key strings on each line from the output, removing duplicates.
Hi,
I also was looking for a solution to "slurp" JSON.sh output into an bash array.
if you output only the leafs with JSON.sh -s -b -n
this will do the trick:
source <( printf 'declare -A JSON=( %s )' "$(JSON.sh -s -b -n <input | sed -E -e 's/\t/=/g' -e 's#\\#\\\\#g')" )
this will be sourced "in place" as:
declare -A JSON=( ["ok"]="true" ["result",0,"update_id"]=146860800 ["result",0,"message","message_id"]=6541 ["result",0,"message","text"]="\\ud83d\\ude02\\ud83d\\ude1d\\ud83d\\udc4c\\u263a\\u2764\\ud83d\\ude15\\ud83d\\ude08#\\u20e3\\ud83c\\udf0f\\ud83c\\udf89\\ud83d\\ude4a\\ud83d\\ude49\\u2615\\ud83d\\ude80\\u2708\\ud83d\\ude82\\ud83d\\udcaf\\u2714\\u303d\\ud83d\\udd1a" ["result",0,"message","from","id"]=123456789 ["result",0,"message","from","is_bot"]="false" ["result",0,"message","from","first_name"]="Kay" ["result",0,"message","from","last_name"]="M" ["result",0,"from","username"]="Gnadelwartz" ["result",0,"message","from","language_code"]="de" ["result",0,"message","chat","id"]=123456789 ["result",0,"message","chat","first_name"]="Test" ["result",0,"message","chat","last_name"]="Bot" ["result",0,"message","chat","username"]="BotTest" ["result",0,"message","chat","title"]="BotTestTitle" ["result",0,"message","chat","type"]="private" ["result",0,"message","date"]=1555822879 )
Now you can use bash array syntax to access the values:
echo ${JSON[ok]}
true
echo ${JSON["result",0,"message","message_id"]}
6541
echo ${JSON["result",0,"update_id"]}
146860800
echo ${JSON["result",0,"message","from","username"]}
Gnadelwartz
echo ${JSON["result",0,"message","photo",4,"file_id"]}
AgADAgADL6oxG-Gw4EndCWGl2WUfUo1pXw8ABDsKqM0vfngJavgDAAEC
In bashbot this makes parsing and assigning JSON five times faster
In case you want to ask how to iterate over the array, see https://stackoverflow.com/questions/3112687/how-to-iterate-over-associative-arrays-in-bash