If your jq has inputs then the simplest would probably be to use it:

jq -ncR '[inputs]' <<< "$groups"
["group1","group2","group3"]

Otherwise, here are three alternatives:

jq -c -n --arg groups "$groups" '$groups | split("\n")' 

echo -n "$groups" | jq -cRs 'split("\n")'

echo "$groups" | jq -R -s -c 'split("\n") | map(select(length>0))'

In any case, the array can easily be incorporated into a JSON object, e.g. by extending the filter with | {groups: .}

If you really want to produce invalid JSON, consider:

printf "%s" "$groups" | jq -Rrsc 'split("\n") | "{ \(.) }"'

Output:

{ ["group_1","group_2","group_3"] }

Note on select(length>0)

Consider:

 jq -Rsc 'split("\n")' <<< $'a\nb'
 ["a","b",""]

The reason for including select(length>0) is to avoid the trailing "".

If $groups contains consecutive newlines, and if it is important to retain the empty strings, then you might want to use [:-1], e.g.

jq -cRs 'split("\n")[:-1]' <<< "$groups"
["group1","group2","group3"]

If your jq does not support [:-1], make the 0 explicit: [0:-1]

Answer from peak on Stack Overflow
Top answer
1 of 4
4

Simply use printf to format the output into JSON

First, you have a very blatant typo in this part of your code right here:

echo "${array[3]:$var-3:4}

Note there is no closing straight quote: ". Fixed it in the rewrite I did below:

But more to the point, doing something like this (using printf) as suggested in this StackOverflow answer. Tested and works in CentOS 7.

#!/bin/bash

readarray -t array <<< "$(df -h)";
var=$(echo "${array[1]}"| grep -aob '%' | grep -oE '[0-9]+');
df_output="${array[3]:$var-3:4}";

manufacturer=$(cat /sys/class/dmi/id/chassis_vendor);
product_name=$(cat /sys/class/dmi/id/product_name);
version=$(cat /sys/class/dmi/id/bios_version);
serial_number=$(cat /sys/class/dmi/id/product_serial);
hostname=$(hostname);
operating_system=$(hostnamectl | grep "Operating System" | cut -d ' ' -f5-);
architecture=$(arch);
processor_name=$(awk -F':' '/^model name/ {print $2}' /proc/cpuinfo | uniq | sed -e 's/^[ \t]*//');
memory$(dmidecode -t 17 | grep "Size.*MB" | awk '{s+=$2} END {print s / 1024"GB"}');
hdd_model=$(cat /sys/block/sda/device/model);
system_main_ip=$(hostname -I);

printf '{"manufacturer":"%s","product_name":"%s","version":"%s","serial_number":"%s","hostname":"%s","operating_system":"%s","architecture":"%s","processor_name":"%s","memory":"%s","hdd_model":"%s","system_main_ip":"%s"}' "$manufacturer" "$product_name" "$version" "$serial_number" "$hostname" "$operating_system" "$architecture" "$processor_name" "$memory" "$hdd_model" "$system_main_ip"

The output I get is this:

{"manufacturer":"Oracle Corporation","product_name":"VirtualBox","version":"VirtualBox","serial_number":"","hostname":"sandbox-centos-7","operating_system":"CentOS Linux 7 (Core)","architecture":"x86_64","processor_name":"Intel(R) Core(TM) i5-1030NG7 CPU @ 1.10GHz","memory":"","hdd_model":"VBOX HARDDISK   ","system_main_ip":"10.0.2.15 192.168.56.20 "}

And if you have jq installed, you can pipe the output of the shell script to jq to “pretty print” the output into some human readable format. Like let’s say your script is named my_script.sh, just pipe it to jq like this:

./my_script.sh | jq

And the output would look like this:

{
  "manufacturer": "Oracle Corporation",
  "product_name": "VirtualBox",
  "version": "VirtualBox",
  "serial_number": "",
  "hostname": "sandbox-centos-7",
  "operating_system": "CentOS Linux 7 (Core)",
  "architecture": "x86_64",
  "processor_name": "Intel(R) Core(TM) i5-1030NG7 CPU @ 1.10GHz",
  "memory": "",
  "hdd_model": "VBOX HARDDISK   ",
  "system_main_ip": "10.0.2.15 192.168.56.20 "
}
2 of 4
1

The following programs can output json:

lshw:

lshw -json

smartmontools v7+:

smartctl --json --all /dev/sda

lsblk:

lsblk --json

lsipc:

lsipc --json

sfdisk

sfdisk --json
🌐
Reddit
reddit.com › r/bash › convert bash array to json with jq
r/bash on Reddit: Convert bash array to JSON with jq
May 2, 2020 -

I am writing a bash script for an Alfred Workflow. In this script I get a list (separated with newlines) from a command that I want to convert into a specific JSON format.

I tried storing the output into an array and parsing that in jq like that:

Command output:

$ piactl get regions

auto
france
netherlands

Create array:

$ IFS=$'\n'
$ regions=($(piactl get regions)) 
$ echo "${regions[@]}"

auto france netherlands

Parse to jq

$ jq -n --arg inarr "${regions}" '{ items: $inarr | split("\n") }'

{
  "items": [
    "auto"
  ]
}

jq only outputs one item of the array and I don't know how to shape the JSON like shown in the wanted output below.

Wanted output:

{"items": [
    {
        "title": "auto",
        "arg": "auto",
        "icon": {
            "path": "icon.png"
        }
    },
    {
        "title": "france",
        "arg": "france",
        "icon": {
            "path": "icon.png"
        }
    },
    {
        "title": "netherlands",
        "arg": "netherlands",
        "icon": {
            "path": "icon.png"
        }
    },
]}

Can somebody help me craft the correct jq arguments for this task?

🌐
Ingernet
ingernet.github.io › bash › jq › json › 2020 › 04 › 16 › json-array-bash-array.html
Converting a JSON array to a bash array
April 16, 2020 - Below, I run a gcloud command and use JQ to grab an array from its JSON output, then do a little sed/regex magic and convert it to proper bash format: # using gcloud output as a source because why not use the hardest shit possible bork=$(gcloud --project=<project-id> container images list-tags us.gcr.io/<project-id>/<image-name> --filter='tags:DEPLOYED' --format=json | jq '.[0].tags') echo $bork [ "260", "61a1d7aef75421f5c209c42304716ba44e86ab7a", "DEPLOYED.2019-11-12T17.04.37.772145800Z", "DEPLOYED.2019-11-13T00.00.29.525908800Z" ] # ^ output is obviously not a bash array # strip out all the
Top answer
1 of 6
36

Using jq :

readarray arr < <(jq '.[].item2' json)
printf '%s\n' "${arr[@]}"

If you need a more hardened way:

readarray -td '' arr

for inputs with newlines or other special characters, avoiding word splitting.

Output:

value2
value2_2

Check:

Process Substitution >(command ...) or <(...) is replaced by a temporary filename. Writing or reading that file causes bytes to get piped to the command inside. Often used in combination with file redirection: cmd1 2> >(cmd2). See http://mywiki.wooledge.org/ProcessSubstitution http://mywiki.wooledge.org/BashFAQ/024

2 of 6
9

The following is actually buggy:

# BAD: Output line of * is replaced with list of local files; can't deal with whitespace
arr=( $( curl -k "$url" | jq -r '.[].item2' ) )

If you have bash 4.4 or newer, a best-of-all-worlds option is available:

# BEST: Supports bash 4.4+, with failure detection and newlines in data
{ readarray -t -d '' arr && wait "$!"; } < <(
  set -o pipefail
  curl --fail -k "$url" | jq -j '.[].item2 | (., "\u0000")'
)

...whereas with bash 4.0, you can have terseness at the cost of failure detection and literal newline support:

# OK (with bash 4.0), but can't detect failure and doesn't support values with newlines
readarray -t arr < <(curl -k "$url" | jq -r '.[].item2' )

...or bash 3.x compatibility and failure detection, but without newline support:

# OK: Supports bash 3.x; no support for newlines in values, but can detect failures
IFS=$'\n' read -r -d '' -a arr < <(
  set -o pipefail
  curl --fail -k "$url" | jq -r '.[].item2' && printf '\0'
)

...or bash 3.x compatibility and newline support, but without failure detection:

# OK: Supports bash 3.x and supports newlines in values; does not detect failures
arr=( )
while IFS= read -r -d '' item; do
  arr+=( "$item" )
done < <(curl --fail -k "$url" | jq -j '.[] | (.item2, "\u0000")')
🌐
Baeldung
baeldung.com › home › scripting › build a json string with bash variables
Build a JSON String With Bash Variables | Baeldung on Linux
August 12, 2024 - Unlike Bash, which dynamically interprets variable types based on context, JSON’s strict syntax ensures consistency and avoids ambiguity in data representation. This rigidity simplifies data exchange between systems and programming languages, ensures consistency, and reduces the risk of type-related errors. ... #!/bin/bash # Bash Variables name="Paco Bellez" age=41 city="Santiago de Compostela" has_car=true languages=("English" "Italian" "Japanese") While age is intended to be a number and has_car to be a boolean value, Bash treats them as strings by default.
Find elsewhere
🌐
GitHub
gist.github.com › ORESoftware › a4e3948b0ce9c22752c759d7e694c9ab
Convert array to JSON in Bash shell · GitHub
April 22, 2018 - Convert array to JSON in Bash shell · Raw · array2json.sh · This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
🌐
Alfred App Community
alfredforum.com › alfred workflows › workflow help & questions
Construct script filter JSON with jq from bash array - Workflow Help & Questions - Alfred App Community Forum
January 30, 2022 - Hi, I am creating a workflow and I want to create a script filter with strings from a bash array. Given I have an array called $regions that contains 3 strings. I want to create 3 list items from that using jq. echo $regions france netherlands denmark I tried this command but the output is obviou...
Top answer
1 of 2
2

Assuming you have the correct values in the shell variables label, last_year, and previous_year and that you want to delete all entries in the options array with the value value $previous_year, and add a new entry with the label value $label and value value $last_year.

jq  --arg add_label "$label" \
    --arg add_value "$last_year" \
    --arg del_value "$previous_year" '
    del(.options[]? | select(.value == $del_value)) |
    .options += [{ label: $add_label, value: $add_value }]' file

This correctly combines the two operations in a single invocation of jq.

The command instantiates three internal jq string variables with values taken from the shell variables that you have previously created. Using --arg to create internal string variables from shell variables ensures that the values are correctly encoded (this avoids code injection vulnerabilities).

As in your code, I use .options[]? rather than just .options[] to avoid an error if the options array does not exist. If it does exist, any entry with a value value of $del_value (an internal variable with the value from the shell variable previous_year) is deleted. You tried to select using the label, but I believe this might have been a typo.

The (possibly) modified document is passed on to the next stage, which adds a new element to the options array. If the array did not previously exist, this would create it with a single element.

Also note that jq does not do in-place editing, which means you will need to redirect the output of the above command to a new name and then replace the original file with that new file. Alternatively, use GNU sponge:

jq ...as above... file | sponge file

(Assuming your file is called file.)

2 of 2
0
#!/bin/bash
file=temp.json
now="$(date)"
previous_year=$(date --date="$(date +'%Y') - 1 year" +%Y)
last_year=$((previous_year + 31))
label=$((last_year -2000))
echo "==============================================================================================================="
echo "| Started parsing json file at script at: $file"
echo "| Started at:                             $now"
echo "| previous year is:                       $previous_year"
echo "| last year to be at json array is:       $last_year"
echo "| label assigned to the last year :       $label"
echo "==============================================================================================================="

if cat $file | grep $previous_year
then
  jq --arg key "$previous_year" 'del(.options[] | select(.value == $key))' $file >> new.json
  jq --arg key "$label" --arg val "$last_year" '.options += [{
        "label": $key,
        "value": $val
      }]' new.json >> new2.json
  mv new2.json $file
  rm new.json
  echo "last year found and parsed"  
else
  echo "nothing to be done"
fi

now="$(date)"
echo "==============================================================================================================="
echo "| Ended script at: $now"
echo "==============================================================================================================="
´´´
🌐
Cameronnokes
cameronnokes.com › blog › working-with-json-in-bash-using-jq
Working with JSON in bash using jq - Cameron Nokes
August 1, 2020 - To me, bash is more expressive and succinct for certain tasks than node is. jq isn’t a built-in command in any environment, so you have to install it. Run brew install jq on macOS. See jq’s install help page for how to install on other environments. jq works similarly to sed or awk — like a filter that you pipe to and extract values from. Also like sed or awk, it basically has it’s own domain specific language (DSL) for querying JSON.
🌐
GitHub
github.com › h4l › json.bash
GitHub - h4l/json.bash: Command-line tool and bash library that creates JSON · GitHub
June 23, 2023 - It's not an alternative to to data-processing tools like jq, rather it helps assemble JSON to send into JSON-consuming tools like jq. ... We publish the container image ghcr.io/h4l/json.bash/jb with jb-* and json.bash, perhaps useful to try without installing.
Starred by 458 users
Forked by 8 users
Languages   Shell 94.9% | Dockerfile 3.6% | HCL 1.5%
🌐
Brazil's Blog
blog.kellybrazil.com › home › blog feed › practical json at the command line
Practical JSON at the Command Line - Brazil's Blog
June 25, 2021 - This is a good start if we just need a single attribute, but many times in our scripts we have multiple items we need to deal with. Assigning a single Bash variable to a JSON attribute can get tedious and slow if we need to iterate over a large dataset. Now, let’s look at assigning more than one item to a Bash variable to use it as a list in a for loop.
🌐
Baeldung
baeldung.com › home › files › conversion of the output of ls command to a json array
Conversion of the Output of ls Command to a JSON Array | Baeldung on Linux
March 18, 2024 - The purpose of ls2json.sh is to convert the output of ls with no additional options into a JSON array, which will therefore be a list of file and directory names. This way, it’s not possible to distinguish which names refer to files and which refer to directories.