简体   繁体   中英

How to populate json file with data from bash variable

I am writing a small bash script and I am stuck. I have a text file with some information and I stored the contents of that file in a bash variable.

tools=$(cat tools.txt)

My tools.txt file looks like this:

docker:19.03.8
go:1.18
kubernetes:1.20

And so on.

What I want is to dynamically create a JSON file named tools.json and to populate that file with the content from tools.txt .

In my tools.json file I have the following structure:

{
    "tools": {

     }
}

And this should be the final structure.

{
    "tools": {
         "name" : "version"
     }
}

So the expected output is:

{
    "tools": {
         "docker" : "19.03.8",
         "go" : "1.18",
         "kubernetes" : "1.20"
     }
}

I don't know how to loop through the $tools variable or tools.txt file in such a way that on each iteration a new line ( "docker": "19.03.8" ) is added to tools.json file.

I tried something like this


cat <<EOF > ./tools.json
{
   "tools": {
        for tool in $tools
        do
                "name" : "version",
        done
   }
}
EOF

Of course, it doesn't work. The idea is that instead of "name": "version" in a loop to use something like "$name": "$version" .

You can use the tool "jq" for that.

https://stedolan.github.io/jq/manual/

I would do something like this:

cat > tools.json << EOF
{
    "tools": {

    }
}
EOF

for item in "${tools[@]}"; do
    tool=$(echo "$item" | cut -d ":" -f1)
    version=$(echo "$item" | cut -d ":" -f2)
    old_content=$(cat tools.json)

    echo "$old_content" | jq \
        --arg TOOL "$tool" \
        --arg VERSION "$version" \
        '.tools += { ($TOOL) : ($VERSION) }' \
        > tools.json
done

A better solution would be:

while IFS=":" read -r tool version; do
    old_content=$(cat tools.json)
    echo "$old_content" | jq \
        --arg TOOL "$tool" \
        --arg VERSION "$version" \
        '.tools += { ($TOOL) : ($VERSION) }' \
        > tools.json
done < tools.txt

Here is how to do it with a simple bash-script:

#!/bin/bash

echo "{"
echo "    \"tools\": {"

while IFS=: read -r name value
do
    echo "        $comma\"$name\": \"$value\""
    comma=","
done < tools.txt

echo "    }"
echo "}"

... just to demonstrate the principle.

Using your already created tools.json file, you can try this sed

$ sed '/tools/{n;s!.*!tac tools.txt|sed "s/^/\t/;2,$ s/$/\\",/;s/$/\\"/"|tac!e};/[a-z]/s/\t\([^:]*\):/\t"\1" : "/g' tools.json
{
    "tools": {
        "docker" : "19.03.8",
        "go" : "1.18",
        "kubernetes" : "1.20"
     }
}

The requirement is quite simple that you don't need loop or jq , you can use only commands and pipes:

λ cat tools.txt 
docker:19.03.8
go:1.18
kubernetes:1.20
printf '{"tools":{'$(
  tr : ' ' <tools.txt |
    xargs printf '"%s":"%s"\n' |
    paste -s -d , -
)'}}\n'
{"tools":{"docker":"19.03.8","go":"1.18","kubernetes":"1.20"}}

Explanation

Use tr xargs printf and paste to generate the JSON tools body part:

tr : ' ' < tools.txt |
  xargs printf '"%s":"%s"\n' |
  paste -s -d , -
"docker":"19.03.8","go":"1.18","kubernetes":"1.20"

Prepend '{"tools":{' and append '}}\n' by printf :

printf '{"tools":{'$(YOUR COMMAND)'}}\n'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM