[英]jq: selecting a subset of keys from an object
給定來自數組的鍵的輸入json字符串,返回一個對象,其中只包含原始對象和輸入數組中具有鍵的條目。
我有一個解決方案,但我認為它不優雅( {($k):$input[$k]}
感覺特別笨重...)並且這是我學習的機會。
jq -n '{"1":"a","2":"b","3":"c"}' \
| jq --arg keys '["1","3","4"]' \
'. as $input
| ( $keys | fromjson )
| map( . as $k
| $input
| select(has($k))
| {($k):$input[$k]}
)
| add'
任何想法如何清理這個?
我覺得從嵌套的JSON對象中提取選定的屬性與jq是一個很好的起點,但我無法讓它工作。
您可以使用此過濾器:
with_entries(
select(
.key as $k | any($keys | fromjson[]; . == $k)
)
)
內部檢查的解決方案:
jq 'with_entries(select([.key] | inside(["key1", "key2"])))'
傑夫的回答有兩個不必要的低效率,假設使用--argjson keys
而不是--arg keys
,以下兩個都解決了這個問題:
with_entries( select( .key as $k | $keys | index($k) ) )
內部操作員大部分時間都在工作; 但是,我剛發現內部操作符有副作用,有時它選擇了不需要的鍵,假設輸入為{ "key1": val1, "key2": val2, "key12": val12 }
並由inside(["key12"])
選擇inside(["key12"])
它將同時選擇"key1"
和"key12"
如果需要完全匹配,請使用in運算符:這樣只選擇.key2
和.key12
jq 'with_entries(select(.key | in({"key2":1, "key12":1})))'
因為in運算符只檢查來自對象的鍵(或者索引是否exists?
於數組中),所以它必須用對象語法編寫,所需的鍵作為鍵,但值無關緊要; 使用in運算符並不是一個完美的用於此目的,我希望看到Javascript ES6包含API的反向版本,以實現為jq builtin
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes
jq 'with_entries(select(.key | included(["key2", "key12"])))'
檢查項目.key
是否included?
從一個數組
這是一些額外的澄清
對於輸入對象{"key1":1, "key2":2, "key3":3}
我想刪除所有不在所需鍵集合中的鍵["key1","key3","key4"]
jq -n --argjson desired_keys '["key1","key3","key4"]' \
--argjson input '{"key1":1, "key2":2, "key3":3}' \
' $input
| with_entries(
select(
.key == ($desired_keys[])
)
)'
with_entries
將{"key1":1, "key2":2, "key3":3}
轉換為以下鍵值對數組,並將select語句映射到數組上,然后將結果數組轉換回對象。
這是with_entries
語句中的內部對象。
[
{
"key": "key1",
"value": 1
},
{
"key": "key2",
"value": 2
},
{
"key": "key3",
"value": 3
}
]
然后我們可以從這個數組中選擇符合我們標准的鍵。
這就是魔術發生的地方......這里是看看這個命令中間發生了什么。 以下命令獲取擴展的值數組,並將它們轉換為我們可以從中選擇的對象列表。
jq -cn '{"key":"key1","value":1}, {"key":"key2","value":2}, {"key":"key3","value":3}
| select(.key == ("key1", "key3", "key4"))'
這將產生以下結果
{"key":"key1","value":1}
{"key":"key3","value":3}
with entries命令可能有點棘手但很容易記住它需要一個過濾器並定義如下
def with_entries(f): to_entries|map(f)|from_entries;
這是一樣的
def with_entries(f): [to_entries[] | f] | from_entries;
困擾人們的問題的另一部分是==
右側的多個匹配
請考慮以下命令。 我們看到輸出是所有左手列表和右手列表的外部產生。
jq -cn '1,2,3| . == (1,1,3)'
true
true
false
false
false
false
false
false
true
如果該謂詞在select語句中,我們在謂詞為真時保持輸入。 請注意,您也可以在此處復制輸入。
jq -cn '1,2,3| select(. == (1,1,3))'
1
1
3
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.