jq で特定条件にマッチする要素を置換する
こういった JSON の .name == "Michel"
の .attributes
だけを置換して全体を出力したい。
/tmp $ cat test.json { "elements": [ { "name": "John", "attributes": { "private": true, "last_login": "2019-11-01 00:00:00" } }, { "name": "Michel", "attributes": { "private": false, "last_login": "2019-11-02 00:00:00" } }, { "name": "Paul", "attributes": { "private": false, "last_login": "2019-11-31 00:00:00" } } ] }
map()
, select()
, |=
, //
, .
を駆使して実現できる。すごく雑に書くと
map()
=>.elements[]
のような配列を map() するselect()
=> 条件に一致するものだけフィルタする//
=>a // b
でa ? a : b
と評価される演算子.
=> イテレートしている要素
キモは //
。
A filter of the form a // b produces the same results as a, if a produces results other than false and null. Otherwise, a // b produces the same results as b.
This is useful for providing defaults: .foo // 1 will evaluate to 1 if there’s no .foo element in the input. It’s similar to how or is sometimes used in Python (jq’s or operator is reserved for strictly Boolean operations).
これらは以下の様に組み合わせて使う。
# 条件にマッチしない場合 `.` (=`.attributes`) に置換する(≒何もしない) /tmp $ cat test.json | jq '.elements |= map((select(0)) // .)' { "elements": [ { "name": "John", "attributes": { "private": true, "last_login": "2019-11-01 00:00:00" } }, { "name": "Michel", "attributes": { "private": false, "last_login": "2019-11-02 00:00:00" } }, { "name": "Paul", "attributes": { "private": false, "last_login": "2019-11-31 00:00:00" } } ] } # 条件にマッチする場合 `elements[].attributes` を `[]` に置換する /tmp $ cat test.json | jq '.elements |= map((select(1).attributes |= []) // .)' { "elements": [ { "name": "John", "attributes": [] }, { "name": "Michel", "attributes": [] }, { "name": "Paul", "attributes": [] } ] }
そして特定条件時のみ .attributes
を置換する
/tmp $ cat test.json | jq '.elements |= map((select(.name == "Michel").attributes |= { private: true, last_login: "2222-22-22 22:22:22"}) // .)' { "elements": [ { "name": "John", "attributes": { "private": true, "last_login": "2019-11-01 00:00:00" } }, { "name": "Michel", "attributes": { "private": true, "last_login": "2222-22-22 22:22:22" } }, { "name": "Paul", "attributes": { "private": false, "last_login": "2019-11-31 00:00:00" } } ] }
202X年もシェル芸は身を助けてくれそうです