Json jq:从对象中选择关键帧的子集
给定一个数组中键的json输入字符串,返回一个对象,其中只包含原始对象和输入数组中有键的条目 我有一个解决方案,但我认为它并不优雅(Json jq:从对象中选择关键帧的子集,json,select,key,subset,jq,Json,Select,Key,Subset,Jq,给定一个数组中键的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
{($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'
你知道怎么清理吗
我觉得这是一个很好的起点,但我无法让它发挥作用。您可以使用此过滤器:
with_entries(
select(
.key as $k | any($keys | fromjson[]; . == $k)
)
)
这里有一些额外的澄清 对于输入对象
{“key1”:1,“key2”:2,“key3”:3}
我想删除不在所需键集中的所有键[“key1”,“key3”,“key4”]
with_entries
将{“key1”:1,“key2”:2,“key3”:3}
转换为以下键值对数组,并将select语句映射到数组上,然后将生成的数组转换回对象
这是语句中带有_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语句中,则当谓词为true时,我们保留输入。注意,您也可以在此处复制输入
jq -cn '1,2,3| select(. == (1,1,3))'
1
1
3
Jeff的回答有一些不必要的低效,这两个问题都可以通过以下方式解决,假设使用了
--argjson-keys
而不是--arg-keys
:
with_entries( select( .key as $k | $keys | index($k) ) )
内部检查解决方案:
jq 'with_entries(select([.key] | inside(["key1", "key2"])))'
内部操作员大部分时间都在工作;然而,我刚刚发现内部操作符有副作用,有时它会选择不需要的键,假设输入是
{“key1”:val1,“key2”:val2,“key12”:val12}
,然后通过内部([“key12”])
选择“key1”
和“key12”
如果需要精确匹配,请使用in运算符:这样将仅选择.key2
和.key12
jq 'with_entries(select(.key | in({"key2":1, "key12":1})))'
由于in运算符仅检查对象中的键(或数组中的索引存在?
),因此必须以对象语法编写,将所需的键作为键,但值并不重要;in操作符的使用并不是实现此目的的完美方法,我希望Javascript ES6包含API的反向版本,以jq内置的形式实现
要检查一项
。key
是否包含?
来自数组从文档中不清楚我可以通过select(.key==(“1”、“3”、“4”)
在==语句的右侧使用()。避免遍历输入键和所需键的整个外积。这不应该是对其他答案的编辑吗?但我可以在同一个线程上有两个答案吗?只是因为有两种不同的方法你可以,但通常你想在同一个答案中对一种方法提出警告,所以在决定合适的方法之前,没有人需要阅读整个Q+A。非常相似的方法通常可以组合成一个答案。仅供参考,这将返回以key1
或key2
开头的任何条目,因此key1234
和key22
也是如此。
jq 'with_entries(select(.key | in({"key2":1, "key12":1})))'
jq 'with_entries(select(.key | included(["key2", "key12"])))'