0

I have a bash associative array containing dynamic data like:

declare -A assoc_array=([cluster_name]="cpod1" [site_name]="ppod1" [alarm_name]="alarm1")

I have to create the JSON data accordingly.

{
"name": "cluster_name",
"value": $assoc_array[cluster_name],
"regex": False
}
{
"name": "site_name",
"value": $assoc_array[site_name],
"regex": False
}
{
"name": "alert_name",
"value": $assoc_array[alert_name],
"regex": False
}

I have used the following code for it:

for i in "${!assoc_array[@]}"; do
    echo $i
    alarmjsonarray=$(echo ${alarmjsonarray}| jq --arg name "$i" \
                                                --arg value "${alarm_param[$i]}" \
                                                --arg isRegex "False" \
                                                '. + [{("name"):$name,("value"):$value,("isRegex"):$isRegex}]')
done
echo "alarmjsonarray" $alarmjsonarray 

I am getting empty string from it. Can you please help me in it?

8
  • 2
    Can you please provide a minimal reproducible example that's complete enough to copy-and-paste without changes? Your current code requires cluster_name, site_name, etc to have values already. Commented May 11, 2021 at 15:57
  • Also, echo ${alarmjsonarray} is in general an antipattern; see I just assigned a variable, but echo $variable prints something else! Commented May 11, 2021 at 15:58
  • okay.. let me edit my question for you... Commented May 11, 2021 at 15:58
  • 1
    (and in general, I'd suggest writing your code to call jq only once instead of calling it in a loop; you can stream your data on input to a single copy of jq and let it turn that into an array). Commented May 11, 2021 at 15:58
  • 1
    What guarantees do you have about values in your strings? Do you need to worry about them containing newlines? What about NULs? Are there other sigils like tabs you can safely use? Commented May 11, 2021 at 16:03

2 Answers 2

4

Assuming the ASCII record separator character \x1e can't occur in your data (and given your assertions that newlines will never be present), one way to handle this would be:

for key in "${!assoc_array[@]}"; do
  printf '%s\x1e%s\n' "$key" "${assoc_array[$key]}"
done | jq -Rn '
[
  inputs |
  split("\u001e") | .[0] as $key | .[1] as $value |
  {"name": $key, "value": $value, "regex": false}
]'

...feel free to change \x1e to a different character (like a tab) that can never exist, as appropriate.

Sign up to request clarification or add additional context in comments.

20 Comments

Can we store the output of it into some variable, as I have take var alarmjsonarray?
result=$(for ...; done | jq ...) will store the stdout of the entire pipeline in result.
I used the following code: alarmjsonarray=$(for key in "${!assoc_array[@]}"; do printf '%s\x1e%s\n' "$key" "${assoc_array[$key]}" done | jq -Rn ' [ inputs | split("\u001e") | .[0] as $key | .[1] as $value | {"name": $key, "value": $value, "regex": false} ]') echo "alarmjsonarray" $alarmjsonarray and I got the following result: alarmjsonarray []
I'd need a minimal reproducible example to be able to address any issues -- tested this before posting it, works for me..
@AadhiVerma, ...see the exact code I tested and its output at gist.github.com/charles-dyfis-net/…
|
1
#!/bin/bash
declare -A assoc_array=([cluster_name]="cpod1" [site_name]="ppod1" [alarm_name]="alarm1")
for i in "${!assoc_array[@]}"; do
  alarmjsonarray=$(echo "${alarmjsonarray:-[]}" |
                   jq --arg name "$i" \
                      --arg value "${assoc_array[$i]}" \
                      --arg isRegex "False" \
                      '. + [{("name"):$name,("value"):$value,("isRegex"):$isRegex}]')
done
echo "alarmjsonarray" "$alarmjsonarray"

array was supposed to be initialized before using it. I thought in bash, scope is there out of block also. Its more simpler way to generate json from bash associative array.

2 Comments

Do make sure you're quoting your expansions -- if you run your code through shellcheck.net, it'll point out the places where this needs to be done. Otherwise, for example, a string " * " in your file can be changed to " a.txt b.txt c.txt " (substituting filenames in your current directory).
Thanks for your suggestion. I have updated my code accordingly. You had been very helpful n kind to me.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.