Добавление / добавление объектов во вновь созданный массив json с теми же ключами через jq в скрипте bash

#arrays #json #bash #append #jq

#массивы #json #bash #добавить #jq

Вопрос:

Мне очень сложно пытаться итеративно добавлять новые значения к вновь созданному массиву / файлу JSON из того же скрипта bash. Рассмотрим следующий простой фрагмент сценария:

 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 .
 

Это выводит:

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

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

Я хочу, чтобы в конечном итоге это делалось примерно так, динамически:

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

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

и т.д…

Я понимаю, что мне нужно будет использовать цикл после первого набора записей key:value, но тогда как я буду добавлять к вновь созданному файлу model.json, а не переопределять начальные значения через jq в скрипте bash?

Большое спасибо

Ответ №1:

Чтобы добавить объект, вы можете использовать идиому:

 .profiles  = [...]
 

Из-за дружественного способа обработки jq null вышеуказанное также будет работать изначально.

Кстати, вы можете сокращать пары ключ-значение, такие как

 "name": $name
 

только к имени переменной:

 $name
 

Пример

Для единообразия может иметь смысл предварительно заполнить model.json null , например

 echo null > model.json
 

Затем вы можете вызывать jq равномерно (без опции -n), например

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

Предостережение: перезапись входного файла с использованием sponge без принятия мер предосторожности имеет свои риски, хотя в этом случае они кажутся небольшими.

Комментарии:

1. Нравится это? jq -n --arg name "$name" --arg car "$car" --arg colour "$colour" '.profiles = [{$name, $car, $colour}]' > model.json Поэтому, когда я добавляю свой цикл между командой jq и первым набором вопросов и ответов, вышеуказанное работает, но не добавляется. Просто переопределяет первый набор значений.

2. Даже если я передам вышеизложенное с | .profiles = [{$name, $car, $colour}]' помощью возвращает тот же набор значений: « { «профили»: [ { «имя»: «Пол», «автомобиль»: «Датсон», «цвет»: «Коричневый» }, { «имя»: «Пол», «автомобиль»: «Datson», «color»: «Brown» } ] } « Дважды вводим последнюю запись.

3. Вы должны отказаться от этой -n опции при чтении из model.json

4. Спасибо, пик. Я использовал описанный вами метод, и, к сожалению, код по-прежнему выводит один набор значений (последний набор записей, которые я ввел). Независимо от того, сколько раз я ввожу значения через цикл, выводится только один набор. Я вижу логику в приведенном выше коде, но не уверен, где я ошибаюсь.

5. Вы уверены, что удалили параметр -n? Возможно, вам следует сначала попробовать самый простой случай, не используя sponge. Добавьте debug операторы jq, чтобы увидеть, что происходит.

Ответ №2:

Использовал метод, описанный выше, и до сих пор не добавляет: 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"
    }
  ]
}