やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

jqで親キー名を取得したい(子要素で条件絞込)

 keysだけならできるのだが絞込と組合せた上でスマートにやりたい。

問題

a.json

{
    "A": { name: "a" },
    "B": { name: "b" }
}

 このときname=="a"の条件に一致する親キー名を取得したい。(この場合はA

 jqでどう書けば抽出できるか。

解法

jq -rc '.[] | if (.name == "a") then .name else "" end' a.json | grep -v '^\s*$'

 一応これでできた。もっとスマートな方法ないか?

解説

 合致しないキーは空行が出力される。if文が冗長。

jq -rc '.[] | if (.name == "a") then .name else "" end' a.json

 grepで空行を削除すれば整形できる。

jq -rc '.profile.info_cache[] | if (.name == "view") then .name else "" end' LocalState.json | grep -v '^\s*$'

探ってみる

複雑な方法

 shellと組み合わせればできた。難しい&長い。

Keys="$(jq -r '. | keys | @tsv' a.json | tr '\t' '\n')"
echo "$Keys" | while read line; do { [ "$line" = "A" ] && { jq -r ".[\"${line}\"].name" a.json; } }; done;
  • jqだけでできないの?
  • json, jq, shellがかかわり煩雑

基礎

 親キー名とnameキー値を出す。

jq -r '. | keys, .[].name' a.json;

 キー一覧を改行区切りにする。

jq -r '. | keys | @tsv' a.json | tr '\t' '\n'

ダメだった方法

 絞り込めない……。

jq -r '.profile.info_cache | select(.[].name == "view")' LocalState.json;

 絞り込めたが親キー名が出ない……。

jq -r '.profile.info_cache[] | select(.name == "view")' LocalState.json;

所感

 しっくりこない。

  • jq自体が難しすぎる。新言語を覚えるレベル(manual
  • jsonを抽出しつつshell構文と相性がよい方法はないものか

 労力に見合わない印象。pythonで書けばいいのでは?

対象環境

$ uname -a
Linux raspberrypi 4.14.98-v7+ #1200 SMP Tue Feb 12 20:27:48 GMT 2019 armv7l GNU/Linux