2014-09-03 72 views
6

值我有一個像這樣與行的文件選擇JQ項目:如何基於陣列

{"items":["blue","green"]} 
{"items":["yellow","green"]} 
{"items":["blue","pink"]} 

如何使用jq選擇並僅顯示在「藍」的JSON值及其「項目」數組?

所以輸出將是:

{"items":["blue","green"]} 
{"items":["blue","pink"]} 
+0

@Tomalak,對不起。 「JSON行」是我應該寫的。 – K2xL 2014-09-03 17:10:59

+0

@Tomalak,你要求什麼代碼?沒有代碼。 – K2xL 2014-09-03 17:25:34

+0

是的,算了吧。我誤解了。我會刪除評論。 – Tomalak 2014-09-03 17:27:06

回答

4

雖然你已經肯定的作品,這將是更正確使用 contains。我會避免使用它,因爲它會導致混淆。 index("blue")0,人們不會認爲這是一個真值,並且可能期望它被排除在結果之外。

考慮使用此過濾器來代替:

select(.items | contains(["blue"])) 

這樣做,如果你通過簡單的陣列添加更多的希望與一個以上的匹配項,它會工作的好處。

正如在評論中指出的那樣,這是不正確的。字符串使用子字符串匹配進行比較(contains被遞歸使用)。

回想起來,contains沒有按照我的想法工作。使用index作品,但我個人不會使用它。通過查找它對我來說感覺不對的索引,找出某個項目是否在某個集合中是有一定意義的。使用contains對我來說更有意義,但根據這些信息,在這種情況下它不會很理想。


這裏是一個應該正常運行的替代:

select([.items[] == "blue"] | any) 

或爲,如果你想能夠匹配更多的價值更加可擴展的方式:

select(.items as $values | ["blue", "yellow"] | map([$values[] == .] | any) | all) 
+0

這個答案是不正確的。儘管在某些情況下它會(危險地)出現,但也可能導致誤報。 「contains」嚴格來說是一個子串搜索。反例:jq -n'[「foobar」,「bar」,「baz」] |包含([「foo」])結果正確。比較:jq -n'[「foobar」,「bar」,「baz」] | (index(「foo」)== null | not)'正確地導致錯誤。 – 2015-07-08 22:46:07

+0

感謝您指出了,我沒有意識到它遞歸地爲陣列運行過濾器。我確信有一種方法可以做到這一點,但仍然具有可擴展性。 – 2015-07-08 23:24:03

+0

我不知道這是否可以縮放,因爲我懷疑在所有情況下都會執行迭代搜索,但我之前也使用過:'jq -n'[「foobar」,「bar」,「baz」 ] | [。[] |選擇(。==「foobar」)] |長度> 0「,它至少有*潛力*並行運行搜索。 – 2015-07-09 00:07:02

3

找到了答案

jq 'select(.items | index("blue"))' 
0

1月30日, 2017年,添加了一個名爲IN的內建程序,用於有效測試流中是否包含JSON實體。它也可以用於高效地測試數組中的成員資格。在目前的情況下,相關的用法是:

select(.items as $items | "blue" | IN($items[])) 

如果您JQ沒有IN/1,那麼只要你的JQ有first/1,您可以使用此對應的定義:

def IN(s): . as $in | first(if (s == $in) then true else empty end) // false; 

(在實際中,index/1通常足夠快,但其目前的實現(jq 1.5和至少在2017年7月的版本)並不理想。)