Как обновить json с помощью массива переменных с помощью сценария bash

У меня есть файл json test.json следующего формата:

{  
   "environments": 
            {
                "egress": [
                   
                ]
            }
}

Я хочу добавить объекты в выходное поле с несколькими значениями переменных. Я написал скрипт bash test.sh с фрагментом кода ниже:

egress_port='[80,443]'
egress_value='[test,test1]'
egress_protocol='[http,https]'
# IFS=','

echo $egress_port
echo $egress_value
echo $egress_protocol

cat test.json |
jq  --argjson port "$egress_port" \
   --argjson value "$egress_value" \
   --argjson protocol "$egress_protocol" \
   '.environments.egress = ([$port, $value, $protocol] | transpose |
   map ({port: .[0], type: "external", value: .[1], protocol: .[2]}))'

Я хочу, чтобы json обновлялся в формате ниже:

{  
   "environments": 
            {
                "egress": [
                   {
                    "port": "80", 
                    "type": "external", 
                    "value": "test", 
                    "protocol": "http"
                   },
                   {
                    "port": "443", 
                    "type": "external", 
                    "value": "test1", 
                    "protocol": "https"
                   }
                ]
            }
}

Когда я запускаю его, он выдает ошибку:

jq: invalid JSON text passed to --argjson

Может ли кто-нибудь помочь мне здесь?

Не создавайте сценарий jq, используя расширение переменных. Если $value_array содержит ", созданный таким образом скрипт не является синтаксически допустимым и jq не может его запустить. Передайте значения сценарию в качестве аргументов, используя --arg или --argjson. Подробности смотрите в документации jq: jqlang.github.io/jq/manual/#invoking-jq

axiac 06.08.2024 16:10

Строка read -a port_array <<< "$egress_port" не имеет никакого смысла, если значения уже сохранены в массиве. Каков ваш точный вариант использования? Известны ли вашему скрипту порты и протоколы или они читаются извне?

axiac 06.08.2024 16:12
Структурированный массив Numpy
Структурированный массив Numpy
Однако в реальных проектах я чаще всего имею дело со списками, состоящими из нескольких типов данных. Как мы можем использовать массивы numpy, чтобы...
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
1
2
60
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Начните с массивов JSON, а не массивов bash для входных данных.

egress_ports='[80, 44]'
egress_values='["test", "test1"]'
egress_protocols='["http", "https"]'

Они будут переданы в качестве аргументов непосредственно фильтру jq, из которого вы

  1. Создайте вложенный массив [[80, 443], ["test", "test1"], ["http", "https"]]
  2. Перенесите это в [[80, "test", "http"], [443, "test1", "https"]]
  3. Создайте массив объектов, используя каждый подмассив как отдельный объект.
  4. Назначьте (или объедините с помощью |=) этот окончательный массив непосредственно с .environments.egress.

jq  --argjson ports "$egress_ports" \
   --argjson values "$egress_values" \
   --argjson protocols "$egress_protocols" \
   '.environments.egress = ([$ports, $values, $protocols] | transpose |
   map ({port: .[0], type: "external", value: .[1], protocol: .[2]}))' test.json
Ответ принят как подходящий

Если вы хотите использовать настоящие массивы Bash, вам нужно будет выполнить цикл:

ports=(80 443)
values=(test test1)
protocols=(http https)
json=$(< test.json)

for i in "${!ports[@]}"; do
    json=$(
        echo "$json" \
        | jq --arg port "${ports[i]}" \
             --arg value "${values[i]}" \
             --arg protocol "${protocols[i]}" \
          '.environments.egress += [
            {$port, $value, $protocol, type: "external"}
          ]'
    )
done

После этого переменная json содержит

{
  "environments": {
    "egress": [
      {
        "port": "80",
        "value": "test",
        "protocol": "http",
        "type": "external"
      },
      {
        "port": "443",
        "value": "test1",
        "protocol": "https",
        "type": "external"
      }
    ]
  }
}

Спасибо @glenn за ваш ответ. Я тоже пробовал это. Но он возвращается пустым, когда я повторяю $json. `ports=(80 443)values=(test test1)protocols=(http https) json=$(< test.json) for i in "${!ports[@]}"; do json=$( echo "$json" \ | jq --arg port "${ports[i]}" \ --arg value "${values[i]}" \ --arg протокол "${protocols[ i]}" \ '.environments.egress += [ {$port, $value, $protocol, type: "external"} ]' ) Done echo $json ` ** sh test.sh возвращает пустую строку. **

AkashR 09.08.2024 19:43

Спасибо @glenn. Я запустил его с помощью bash test.sh, и он вернул заполненный json. Еще раз спасибо!!!

AkashR 09.08.2024 20:11

Другие вопросы по теме