Json 使用jq合并具有公共id的密钥
考虑一个文件“b.json”:Json 使用jq合并具有公共id的密钥,json,key,jq,Json,Key,Jq,考虑一个文件“b.json”: [ { "id": 3, "foo": "cannot be replaced, id isn't in a.json, stay untouched", "baz": "do not touch3" }, { "id": 2, "foo": "should be replaced with 'foo new2'", "baz": "do not touch2" } ] 和“a.json”: [
[
{
"id": 3,
"foo": "cannot be replaced, id isn't in a.json, stay untouched",
"baz": "do not touch3"
},
{
"id": 2,
"foo": "should be replaced with 'foo new2'",
"baz": "do not touch2"
}
]
和“a.json”:
[
{
"id": 2,
"foo": "foo new2",
"baz": "don't care"
}
]
我想使用jq和a.json中的匹配值更新b.json中的键“foo”。它还可以处理a.json中的多个条目
因此,期望的输出是:
[
{
"id": 3,
"foo": "cannot be replaced, id isn't in a.json, stay untouched",
"baz": "do not touch3"
},
{
"id": 2,
"foo": "foo new2",
"baz": "do not touch2"
}
]
下面是使用
索引/2
的几种可能性之一。如果您的jq没有内置此功能,请参见下文
jq --argfile a a.json '
INDEX($a[]; .id) as $dict
| map( (.id|tostring) as $id
| if ($dict|has($id)) then .foo = $dict[$id].foo
else . end)' b.json
还有其他方法可以传递a.json和b.json的内容
警告
上述索引的使用假设不存在“冲突”,例如,如果其中一个对象的.id等于1,而另一个对象的.id等于“1”,则会发生这种情况。如果存在这种冲突的可能性,则可以使用更复杂的索引定义
INDEX/2
直接从builtin.jq:
def INDEX(stream; idx_expr):
reduce stream as $row ({}; .[$row|idx_expr|tostring] = $row);
这里有一个通用的答案,除了它们是不同的JSON值外,不对.id键的值进行任何假设 索引/2的推广 调用 主要的
给你,但没有什么新东西。“baz”不应该被改变这个问题已经存在。你的问题是关于通用JSON操作的,如果你愿意,我可以为你提供一个替代的(非jq)简单解决方案。@Dmitry非常感谢你,但我只有基本的工具(grep、sed、sh和jq)在目标机器上,无法安装额外的软件包,我坚持使用JQT非常感谢,这非常有效。我需要一段时间才能真正理解这里发生了什么。
def type2: [type, if type == "string" then . else tojson end];
def dictionary(stream; f):
reduce stream as $s ({}; setpath($s|f|type2; $s));
def lookup(value):
getpath(value|type2);
def indictionary(value):
(value|type2) as $t
| has($t[0]) and (.[$t[0]] | has($t[1]));
jq --argfile a a.json -f program.jq b.json
dictionary($a[]; .id) as $dict
| b
| map( .id as $id
| if ($dict|indictionary($id))
then .foo = ($dict|lookup($id).foo)
else . end)