私は尋ねたエマルジョンただし、この問題に対する解決策を適用する際に問題があります。
次のjson配列があります。
$ jq <<<"$json"
[
{
"id": "node1"
},
{
"id": "node2"
},
{
"id": "node3"
}
]
各ノードにキー/値を追加するか、すでに存在する場合は変更したいと思います。私はこれを行うことができます:
$ jq '.[] | select(.id == "node2") += {status: "fail"}' <<<"$json"
{
"id": "node1"
}
{
"id": "node2",
"status": "fail"
}
{
"id": "node3"
}
ただし、外部配列が消えるので、このソリューションをスクリプトで実装しようとすると失敗します。
#!/usr/bin/env bash
[[ $DEBUG == true ]] && set -x
nodes=(node1 node2 node3)
json='[{"id": "node1"},{"id": "node2"},{"id": "node3"}]'
for node in "${nodes[@]}"; do
if [[ $node == node2 ]]; then
status=fail
else
status=pass
fi
json=$(jq --arg status "$status" --arg node "$node" '.[] | select(.id == $node) += {status: $status}' <<<"$json")
done
間違い:
$ ./script.sh
jq: error (at <stdin>:4): Cannot index string with string "id"
jq: error (at <stdin>:7): Cannot index string with string "id"
jq: error (at <stdin>:10): Cannot index string with string "id"
構造全体を維持しながらこれらのjsonオブジェクトを変更する方法はありますか?
答え1
.[]
で要素を選択すると、select()
それが残った唯一のデータであり、最後に出力される内容です。
代わりに、次map()
を使用して、最上位配列の各要素に(可能な)修正を適用します。
$ jq --arg id node2 --arg status fail 'map(select(.id == $id) += { status: $status } )' file
[
{
"id": "node1"
},
{
"id": "node2",
"status": "fail"
},
{
"id": "node3"
}
]
または、括弧の数が少なく、よりきれいになる可能性があります。
$ jq --arg id node2 --arg status fail 'map(select(.id == $id).status = $status)' file
[
{
"id": "node1"
},
{
"id": "node2",
"status": "fail"
},
{
"id": "node3"
}
]
jq
複数の呼び出しを避けるためにシェルループをコピーしてくださいjq
。
$ jq --arg failnode node2 'map(.status = if .id == $failnode then "fail" else "pass" end)' file
[
{
"id": "node1",
"status": "pass"
},
{
"id": "node2",
"status": "fail"
},
{
"id": "node3",
"status": "pass"
}
]
--args
または、複数のノードに障害が発生し、障害が発生した各ノードをコマンドラインにリストします(通常ではありませんが、最後に必要な配置に注意してください)。
$ jq 'map(.status = if (.id|IN($ARGS.positional[])) then "fail" else "pass" end)' file --args node1 node2
[
{
"id": "node1",
"status": "fail"
},
{
"id": "node2",
"status": "fail"
},
{
"id": "node3",
"status": "pass"
}
]