2016-09-30 13 views
3

非常に大きな入れ子になったjson構造では、キーで終わるすべてのパスを見つけることを試みています。jqを使用して特定のキーへのすべてのパスを見つける方法

例: [ "A"、 "A1"、 "foo" という]、[ "foo" という]


残念ながら、私は:

{ 
    "A": { 
    "A1": { 
     "foo": { 
     "_": "_" 
     } 
    }, 
    "A2": { 
     "_": "_" 
    } 
    }, 
    "B": { 
    "B1": {} 
    }, 
    "foo": { 
    "_": "_" 
    } 
} 

はの線に沿って何かを印刷しますどのレベルのネストでキーが表示されるかわからないので、簡単な選択でそれを把握することはできませんでした。私はjq '[paths] | .[] | select(contains(["foo"]))'に近づいていますが、出力にはfooを含むツリーのすべての順列が含まれています。 出力:["A", "A1", "foo"]["A", "A1", "foo", "_"]["foo"][ "foo", "_"]

オリジナルのデータ構造形式を維持できても、キーを含まないすべてのパスを単に除外することができます(この場合、「foo」の下のサブツリーは非表示にする必要はありません)。まだ

$ jq 'fromstream(tostream| select(.[0]|index("foo")))' 

以上、あなたの入力が大きいため、次のことができます。

$ jq -c 'paths | select(.[-1] == "foo")' 
["A","A1","foo"] 
["foo"] 

ボーナスポイント:

(1)あなたのJQはtostreamを持っている場合は、あなたの入力して

+0

どのように 'endswith'で' contains'の交換について? –

答えて

4

このフィルタでストリーミングパーサー(jq -n --stream)を使用します。

fromstream(inputs|select((.[0]|index("foo")))) 

(2)あなたのJQはtostreamを持っているかどうかは:3つのすべてのケースで

. as $in 
| reduce (paths(scalars) | select(index("foo"))) as $p 
    (null; setpath($p; $in|getpath($p)))) 

、出力は次のとおりです。

{ 
    "A": { 
    "A1": { 
     "foo": { 
     "_": "_" 
     } 
    } 
    }, 
    "foo": { 
    "_": "_" 
    } 
} 
関連する問題