jq で特定条件にマッチする要素を置換する
November 21, 2019
こういった 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).
[https://stedolan.github.io/jq/manual/#Alternativeoperator://:embed:cite]
これらは以下の様に組み合わせて使う。
# 条件にマッチしない場合 `.` (=`.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年もシェル芸は身を助けてくれそうです