まとめ
jq(yq)のwith_entries
, select
, test
を組み合わせるとオブジェクトのキー名の正規表現でフィルタをかけることができる。
# regexには正規表現のパターンを記述する
jq "with_entries(select(.key|test(\"${regex}\")))"
yq "with_entries(select(.key|test(\"${regex}\")))"
環境
キーに正規表現を当てる
こんな感じのJSONまたはYAMLについて、.config
配下のspec111
とspec222
の要素だけを正規表現で抜きたいとする。
こんなときはwith_entries
とselect
, test
を使うと良い感じにできる。
# 先頭がspecで始まり数字で終わるパターン
$ regex='^spec[0-9]+$'
$ cat example.json | jq ".config | with_entries(select(.key|test(\"${regex}\")))"
{
"spec111": {
"aaa": 123,
"bbb": 456
},
"spec222": {
"aaa": "abc",
"bbb": "def"
}
}
$ cat example.yaml | yq ".config | with_entries(select(.key|test(\"${regex}\")))"
spec111:
aaa: 123
bbb: 456
spec222:
aaa: abc
bbb: def
なにが起こっているのか
jq Manualによるとwith_entries(foo)
はto_entries | map(foo) | from_entries
と同じ意味なので、
先ほどのコマンドを下記のように分解して何が起こっているのか詳細を追っていく。
(yqについてもjqとほぼ同じはず)
# 下記2行は同じ操作
jq ".config | with_entries(select(.key|test(\"${regex}\")))"
jq ".config | to_entries | map(select(.key|test(\"${regex}\"))) | from_entries"
# yqについても同じ
yq ".config | with_entries(select(.key|test(\"${regex}\")))"
yq ".config | to_entries | map(select(.key|test(\"${regex}\"))) | from_entries"
まずはto_entries
から。
これを噛ませるとキーの文字列に.key
としてアクセスできるようになる。
https://stedolan.github.io/jq/manual/#to_entries,from_entries,with_entries
https://mikefarah.gitbook.io/yq/operators/entries
$ cat example.json | jq ".config | to_entries"
[
{
"key": "spec111",
"value": {
"aaa": 123,
"bbb": 456
}
},
{
"key": "spec222",
"value": {
"aaa": "abc",
"bbb": "def"
}
},
{
"key": "metadata",
"value": {
"hoge": "fuga"
}
}
]
$ cat example.yaml | yq ".config | to_entries"
- key: spec111
value:
aaa: 123
bbb: 456
- key: spec222
value:
aaa: abc
bbb: def
- key: metadata
value:
hoge: fuga
to_entries
を噛ませた結果は配列として出力されるので、
この配列の要素を正規表現でフィルタするためにmap
, select
, test
を噛ませてやる。
https://stedolan.github.io/jq/manual/#map(x),map_values(x)
https://stedolan.github.io/jq/manual/#select(boolean_expression)
https://stedolan.github.io/jq/manual/#test(val),test(regex;flags)
https://mikefarah.gitbook.io/yq/operators/map
https://mikefarah.gitbook.io/yq/operators/select
https://mikefarah.gitbook.io/yq/operators/string-operators#test-using-regex
select
, test
の条件にto_entries
で追加された.key
を指定することでキー名で正規表現をかけることができる。
$ regex='^spec[0-9]+$'
$ cat example.json | jq ".config | to_entries | map(select(.key|test(\"${regex}\")))"
[
{
"key": "spec111",
"value": {
"aaa": 123,
"bbb": 456
}
},
{
"key": "spec222",
"value": {
"aaa": "abc",
"bbb": "def"
}
}
]
$ cat example.yaml | yq ".config | to_entries | map(select(.key|test(\"${regex}\")))"
- key: spec111
value:
aaa: 123
bbb: 456
- key: spec222
value:
aaa: abc
bbb: def
あとはto_entries
のフォーマットの配列をfrom_entries
で元のキーと値の形式に戻してやる。
$ regex='^spec[0-9]+$'
$ cat example.json | jq ".config | to_entries | map(select(.key|test(\"${regex}\"))) | from_entries"
{
"spec111": {
"aaa": 123,
"bbb": 456
},
"spec222": {
"aaa": "abc",
"bbb": "def"
}
}
$ cat example.yaml | yq ".config | to_entries | map(select(.key|test(\"${regex}\"))) | from_entries"
spec111:
aaa: 123
bbb: 456
spec222:
aaa: abc
bbb: def
最初のコマンドと同じ結果が得られた。
おわり
jq(yq)でオブジェクトのキーに対して正規表現でフィルタをかけることができた。
マジで便利。