簡體   English   中英

根據jq中的多個值選擇條目

[英]Select entries based on multiple values in jq

我正在和JQ合作,到目前為止我非常喜歡它。 我遇到了一個問題,我還沒有找到其他地方的解決方案,並希望看看社區是否有辦法做到這一點。

我們假設我們有一個看起來像這樣的JSON文件:

{"author": "Gary", "text": "Blah"}
{"author": "Larry", "text": "More Blah"}
{"author": "Jerry", "text": "Yet more Blah"}
{"author": "Barry", "text": "Even more Blah"}
{"author": "Teri", "text": "Text on text on text"}
{"author": "Bob", "text": "Another thing to say"}

現在,我們想要選擇author的值等於“Gary”或“Larry”的行,但沒有其他情況。 實際上,我有幾千個我正在檢查的名字,所以只需說明直接或有條件的(例如cat blah.json | jq -r 'select(.author == "Gary" or .author == "Larry")' )是不夠的。 我試圖通過inside函數這樣做,但得到一個錯誤對話框:

cat blah.json | jq -r 'select(.author | inside(["Gary", "Larry"]))'
jq: error (at <stdin>:1): array (["Gary","La...) and string ("Gary") cannot have their containment checked

做這樣的事情最好的方法是什么?

IRC用戶gnomon在jq頻道上回答如下:

jq 'select([.author] | inside(["Larry", "Garry", "Jerry"]))'

根據用戶的說法,這種方法背后的直覺是:“字面上你的想法,只包裝.author作為[.author]強制它成為一個單項數組,所以inside()將在它上面工作。” 此答案為列表中提供的一系列名稱生成所需的過濾結果,作為所需的原始問題。

insidecontains有點奇怪。 以下是一些更直接的解決方案:

索引/ 1

select( .author as $a | ["Gary", "Larry"] | index($a) )

任何/ 2

["Gary", "Larry"] as $whitelist
| select( .author as $a | any( $whitelist[]; . == $a) )

使用字典

如果性能是一個問題,如果“author”始終是一個字符串,那么應該考慮@JeffMercado建議的解決方案。 這是一個變體(與-n命令行選項一起使用):

["Gary", "Larry"] as $whitelist
| ($whitelist | map( {(.): true} ) | add) as $dictionary
| inputs
| select($dictionary[.author])

您可以使用對象,就像它們設置為測試成員資格一樣。 在陣列上操作的方法效率低,特別是如果陣列可能很大。

您可以在讀取輸入之前構建一組值,然后使用該集來過濾輸入。

$ jq -n --argjson names '["Larry","Garry","Jerry"]' '
(reduce $names[] as $name ({}; .[$name] = true)) as $set
    | inputs | select($set[.author])
' blah.json

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM