[英]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()
將在它上面工作。” 此答案為列表中提供的一系列名稱生成所需的過濾結果,作為所需的原始問題。
inside
和contains
有點奇怪。 以下是一些更直接的解決方案:
select( .author as $a | ["Gary", "Larry"] | index($a) )
["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.