1

I am having a real hard time in attempting to iteratively append new values over a newly created JSON array/file from the same bash script. Consider the following simple script snippet:

echo "Enter name: "
read name
echo "Enter Car Model: "
read car
echo "Enter Colour: "
read colour

echo
jq -n --arg name "$name" --arg car "$car" --arg colour "$colour" '{"profiles":[{"name": $name, "car": $car, "colour": $colour}]}' > model.json
echo
cat model.json | jq .

This outputs:

Enter name:
Joe
Enter Car Model:
BMW
Enter Colour:
Red

{
  "profiles": [
    {
      "name": "Joe",
      "car": "BMW",
      "colour": "Red"
    }
  ]
}

What I want it to eventually do is something like this, dynamically:

Enter name:
Joe
Enter Car Model:
BMW
Enter Colour:
Red

{
  "profiles": [
    {
      "name": "Joe",
      "car": "BMW",
      "colour": "Red"
    },
    {
      "name": "Peter",
      "car": "Nissan",
      "colour": "White"
    }
  ]
}

etc...

I understand I'll need to utilise a loop after the first set of key:value entries, but then how would I append to the newly created model.json file as opposed to overriding the initial values via jq in a bash script?

Many Thanks

2 Answers 2

1

To append the object, you can use the idiom:

.profiles += [...]

Because of the friendly way jq handles null, the above will also work initially.

Incidentally, you can abbreviate key-value pairs such as

"name": $name

to just the variable name:

$name

Example

For the sake of uniformity, it might make sense to prepopulate model.json with null, e.g.

echo null > model.json

Then you can invoke jq uniformly (without the -n option), e.g.

jq --arg name "$name" --arg car "$car" --arg colour "$colour" '
  .profiles += [{ $name, $car, $colour}]
' model.json | sponge model.json

Caveat: overwriting the input file using sponge without taking precautions has its risks, though in this case they would seem to be small.

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

12 Comments

Like this? jq -n --arg name "$name" --arg car "$car" --arg colour "$colour" '.profiles += [{$name, $car, $colour}]' > model.json So when I add my loop between the jq command and the first set of q&a's, the above works but does not append. Simply overrides the first set of values.
Even if I pipe the above with | .profiles += [{$name, $car, $colour}]' Returns the same set of values: ``` { "profiles": [ { "name": "Paul", "car": "Datson", "colour": "Brown" }, { "name": "Paul", "car": "Datson", "colour": "Brown" } ] } ``` Taking the last entry twice.
You should drop the -n option when reading from model.json
Thank you peak. I have utilised the method you've outlined and unfortunately, the code is still outputting one set of values (The last set of entries I've input). No matter how many times I enter values via the loop, only one set is output. I see the logic in the above code, but not sure where I am going wrong.
Are you sure you have removed the -n option? Perhaps you should try the very simplest case first, without using sponge. Add jq debug statements to see what's going on.
|
0

Utilised the method above and still does not append: ie.

Enter name:
Joe
Enter Car Model:
BMW
Enter Colour:
Blue

Add a new entry? (y/n):  y
Enter name:  
Paul
Enter Car Model:  
Nissan
Enter Colour:  
Black

Add a new entry? (y/n):  n



{
  "profiles": [
    {
      "name": "Paul",
      "car": "Nissan",
      "colour": "Black"
    }
  ]
}

Comments

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.