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年もシェル芸は身を助けてくれそうです