Я пытаюсь добавить объект {...} в родительский [...] с помощью jq.

Но следующее

parent="[]"


block=$(cat << EOF
{
    "block_id": "$block_id",
    "block_parent_id": "$block_parent_id",
    "current_index": 0,
    "child_sum": 0,
    "block_cidr": "",
    "block_size": "",
    "child_cidr": "",
    "child_size": "",
    "subnets": []
}
EOF
)

jq --arg ITEM "$block" '.+[$ITEM]' <<< "$parent"

Дает

[
  "{\n\t\"block_id\": \"\",\n\t\"block_parent_id\": \"\",\n\t\"current_index\": 0,\n\t\"child_sum\": 0,\n\t\"block_cidr\": \"\",\n\t\"block_size\": \"\",\n\t\"child_cidr\": \"\",\n\t\"child_size\": \"\",\n\t\"subnets\": []\n}"
]

Как видите, escape-символы, такие как \n и \t, кодируются буквально. Как добавить элемент в родительский [] с правильно переведенными escape-символами (например, \n -> новая строка)?

См. https://replit.com/@LoganLee7/jq -add-item-encodes-nt#main.sh

0
Logan Lee 10 Ноя 2021 в 03:17

2 ответа

Проблема двоякая:

  1. Вы передаете JSON в jq, используя --arg, который ожидает текст. Это означает, что jq будет JSON-кодировать данный текст в строку. У утилиты jq есть отдельная опция --argjson, когда передаваемые данные представляют собой документ JSON.

  2. В самом общем случае вы не хотите внедрять переменные оболочки в документ JSON без кодирования их содержимого. Вы делаете это, передавая данные переменной в jq с помощью --arg или используя какой-либо другой инструмент (например, jo), который ожидает ввода не в формате JSON и создает вывод в формате JSON.

  • Вы также используете [] без кавычек, что заставит оболочку жаловаться, если у нее установлена ​​опция оболочки failglob (или эквивалентная, например nomatch в zsh). Оболочка zsh по умолчанию имеет параметр оболочки nomatch.

Вашу проблему лучше всего решить, используя jq для добавления данных непосредственно в существующий документ:

jq \
        --arg block_id "$block_id" \
        --arg block_parent_id "$block_parent_id" \
        --argjson current_index 0 \
        --argjson child_sum 0 \
        --arg block_cidr "" \
        --arg block_size "" \
        --arg child_cidr "" \
        --arg child_size "" \
        '. += [ $ARGS.named | .subnets = $ARGS.positional ]' \
        --args \
        <<<"$parent"

В приведенной выше команде я создаю объект, который добавляю в существующий список в $parent, используя $ARGS.named для каждой простой (скалярной) пары ключ-значение. Значение $ARGS.named — это объект с ключами и значениями, взятыми из параметров --arg и их значений. Затем я добавляю массив subnets с помощью $ARGS.positional. Это значение представляет собой массив значений после --args в командной строке. Параметр --args должен быть последним параметром в командной строке, а в приведенной выше команде список пуст.

Если вы хотите создать объект, который вы добавляете отдельно:

to_add=$(
jq -n \
        --arg block_id "$block_id" \
        --arg block_parent_id "$block_parent_id" \
        --argjson current_index 0 \
        --argjson child_sum 0 \
        --arg block_cidr "" \
        --arg block_size "" \
        --arg child_cidr "" \
        --arg child_size "" \
        '[ $ARGS.named | .subnets = $ARGS.positional ]' \
        --args
)

jq --argjson block "$to_add" '. += $block' <<<"$parent"
0
they 11 Дек 2021 в 00:31

Я нашел ответ:

jq --arg ITEM "$block" '.+[$ITEM|fromjson]' <<< "$parent"

Или

jq --argjson ITEM "$block" '.+[$ITEM]' <<< "$parent"
0
Logan Lee 10 Ноя 2021 в 03:22