0

I came up with this one liner to parse JSON output of AWS commands and use the values. It does work, somehow though it feels wrong :) The only stuff on it I could find was how to convert a known "key":"value" pairs, mine does any seemingly. Will appreciate any feedback.

rm -f tmp.file
cmd="aws sns list-subscriptions-by-topic --topic-arn arn:aws:sns:eu-west-1:${account}:${topic}"
#this is the command that produces JSON
eval "${cmd}" | jq . | tr -d "{" | tr -d "}" | tr -d "," | tr -d "[" | tr -d "]" | tr -d " " | grep -v '^[[:space:]]*$' | while read LINE; do 
# The above line strips JSON-specific chars and feeds what is left line by line into a loop
    varname=$(echo "${LINE}" | cut -d ":" -f1 | tr -d '"')
#key is whatever comes before ":"
    value=$(echo "${LINE}" | cut -d ":" -f2-)
#value is whatever comes after ":"
    if [ "${value}" != "" ]; then 
       echo "${varname}+=(${value})" >> tmp.file
       #we create a temp file that adds values to an array named by key elements
    fi
done
#here we source the tmp.file and remove it
source tmp.file & rm -f tmp.file

This does what I am expecting it to do, the question is - does it fit all possible cases of JSON output for AWS or will I be stuck debugging it forever in the real world? :)

  • 2
    Not remotely efficient. jq itself can directly write shell syntax as output; you should never be taking it as input to a mess of tr/sed/whatnot – Charles Duffy Jul 19 '23 at 13:15
  • (moreover, generating code that's going to be later executed by a shell is a fast route to injection vulnerabilities; it's only safe to do in jq if you use `@sh`, which performs POSIX-compliant escaping, and if you don't use _some_ kind of escaping it's not safe at all). – Charles Duffy Jul 19 '23 at 13:19
  • thanks!!! can you point me please into direction of correct jq syntax that would do that? – sheikhness Jul 19 '23 at 13:22
  • (BTW, these aren't _environment_ variables: you can't export an array to the environment) – Charles Duffy Jul 19 '23 at 13:24
  • in the linked duplicates it would add already known key names. I need mine to work with any "cmd" that has JSON output... unless I am missing something, its not really that – sheikhness Jul 19 '23 at 13:26
  • I don't see any environment variables in your code being set..... BTW: Your approach will break, if `account` or `topic` contains a space. Don't know whether this can occur though. – user1934428 Jul 19 '23 at 13:27
  • `to_entries` goes from an object to a set of `{"key": key, "value": value}` items; iterating over those gives you arbitrary pairs. – Charles Duffy Jul 19 '23 at 13:28
  • So, as a starting point, assuming the key names are trusted but the value strings aren't: `jq -r '.Subscriptions[] | to_entries[] | "\(.key)=\(.value|@sh)"'` – Charles Duffy Jul 19 '23 at 13:30
  • Added another duplicate that explicitly works with arbitrary objects. – Charles Duffy Jul 19 '23 at 13:32
  • (or given the appending-to-an-array context, `"\(.key)+=( \(.value|@sh) )"`) – Charles Duffy Jul 19 '23 at 13:38
  • Thanks! That does it!!!! Appreciate your help! Should I delete the question? – sheikhness Jul 19 '23 at 13:59

0 Answers0