Как обновить 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

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

🤔 А знаете ли вы, что...
С Bash можно создавать скрипты, которые мониторят системные ресурсы и производительность.


1
60
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"
      }
    ]
  }
}