2015-12-08 66 views
3

說我有這樣的JSON:如何使用jq獲取找到的值的索引路徑?

{ 
    "json": [ 
    "a", 
    [ 
     "b", 
     "c", 
     [ 
     "d", 
     "foo", 
     1 
     ], 
     [ 
     [ 
      42, 
      "foo" 
     ] 
     ] 
    ] 
    ] 
} 

而且我要的是含有foojq指數路徑的數組:使用jq以及如何

[ 
    ".json[1][2][1]", 
    ".json[1][3][0][1]" 
] 

我能做到這一點? 我試過recurse | .foo首先得到比賽,但是我收到一個錯誤:Cannot index array with string "foo"

回答

5

首先,我不確定獲得一組jq程序的目的是什麼。雖然存在這樣做的手段,但它們很少有必要; jq不提供任何種類的eval命令。

jq有一個路徑的概念,它是一個字符串和數字的數組,表示JSON中元素的位置;這相當於預期輸出中的字符串。舉例來說,".json[1][2][1]"將被表示爲["json", 1, 2, 1]。標準庫包含幾個可以用這個概念運行的功能,如getpath,setpath,pathsleaf_paths

我們因此可以得到在給定的JSON所有葉的路徑和遍歷它們,選擇那些對其中它們在輸入值JSON是「foo」的,併產生一個陣列了出來:

jq '[paths as $path | select(getpath($path) == "foo") | $path]' 

這將返回,您給定的輸入,輸出如下:

[ 
    ["json", 1, 2, 1], 
    ["json", 1, 3, 0, 1] 
] 

現在,雖然它不應該是必要的,而且是最有可能的,你正在接近任何問題,你都面臨着在錯誤的道路標誌,可以將這些數組轉換爲jq路徑字符串

".\(map("[\(tojson)]") | join(""))" 

完整的腳本將因此會:通過下面的腳本將每個路徑尋求

jq '[paths as $path | select(getpath($path) == "foo") | $path | ".\(map("[\(tojson)]") | join(""))"]' 

,其輸出是:

[ 
    ".[\"json\"][1][2][1]", 
    ".[\"json\"][1][3][0][1]" 
] 
+0

太棒了,謝謝! –

+1

錯誤的方法來解決這個問題,這個答案有助於更好地理解jq是如何工作的。謝謝! :) – Kaos

3

聖地亞哥的優秀節目可以進一步調整以產生所需格式的輸出:

def jqpath: 
    def t: test("^[A-Za-z_][A-Za-z0-9_]*$"); 
    reduce .[] as $x 
    (""; 
    if ($x|type) == "string" 
    then . + ($x | if t then ".\(.)" else ".[" + tojson + "]" end) 
    else . + "[\($x)]" 
    end); 

[paths as $path | select(getpath($path) == "foo") | $path | jqpath] 


jq -f wrangle.jq input.json 

[ 
    ".json[1][2][1]", 
    ".json[1][3][0][1]" 
] 
相關問題