替换 jq 中没有确切路径的子项
Replace subkey without exact path in jq
示例 JSON 文件:
{
"u": "stuff",
"x": [1,2,3],
"y": {
"field": "value"
},
"z": {
"zz": {
"name": "change me",
"more": "stuff"
},
"randomKey": {
"name": "change me",
"random": "more stuff"
}
}
}
如何将所有名称字段更新为 "something",同时保持 JSON 文件的其余部分不变?
{
"u": "stuff",
"x": [1,2,3],
"y": {
"field": "value"
},
"z": {
"zz": {
"name": "something",
"more": "stuff"
},
"randomKey": {
"name": "something",
"random": "more stuff"
}
}
}
使用直接路径,这会很容易,但父键(在这种情况下为 z 和 randomKey)会有所不同。
我试过类似的方法:
jq '.z | .. | .name? |= "something"' file.json
它正在更新名称,但也放入所有递归的东西..
如果在任何地方更改 "name" 字段是可以接受的,您可以使用 walk/1
:
walk(if type == "object" and has("name") then .name = "something" else . end)
请注意,walk/1
仅在 jq 1.5 发布后才包含在 jq 中。如果你的jq没有,那么你可以在jq FAQ上找到它的定义,例如
如果您只想修改 "z" 上下文中的 "name" 字段,请考虑:
.z |= with_entries(if .value.name?
then .value.name = "something"
else . end)
假设 z
中的每个值都有一个名称 属性,您可以这样做:
$ jq --arg newname 'something' '.z[].name = $newname' input.json
对对象使用 []
将产生该对象中包含的所有值。对于这些值中的每一个,我们只是将 name
设置为新名称。
如果您需要对要更新的内容更具选择性,则必须为要更新的对象添加更多条件。一般来说,我会使用 peak 的方法,但这里有另一种方法可以使用类似于第一种方法的结构来实现,假设我们只想更新已经有 name
属性 的对象:
$ jq --arg newname 'something' '(.z[] | select(has("name")).name) = $newname' input.json
将赋值的 LHS 括在括号中很重要,我们不想在赋值之前更改上下文,否则我们将看不到其余结果。
示例 JSON 文件:
{
"u": "stuff",
"x": [1,2,3],
"y": {
"field": "value"
},
"z": {
"zz": {
"name": "change me",
"more": "stuff"
},
"randomKey": {
"name": "change me",
"random": "more stuff"
}
}
}
如何将所有名称字段更新为 "something",同时保持 JSON 文件的其余部分不变?
{
"u": "stuff",
"x": [1,2,3],
"y": {
"field": "value"
},
"z": {
"zz": {
"name": "something",
"more": "stuff"
},
"randomKey": {
"name": "something",
"random": "more stuff"
}
}
}
使用直接路径,这会很容易,但父键(在这种情况下为 z 和 randomKey)会有所不同。
我试过类似的方法:
jq '.z | .. | .name? |= "something"' file.json
它正在更新名称,但也放入所有递归的东西..
如果在任何地方更改 "name" 字段是可以接受的,您可以使用 walk/1
:
walk(if type == "object" and has("name") then .name = "something" else . end)
请注意,walk/1
仅在 jq 1.5 发布后才包含在 jq 中。如果你的jq没有,那么你可以在jq FAQ上找到它的定义,例如
如果您只想修改 "z" 上下文中的 "name" 字段,请考虑:
.z |= with_entries(if .value.name?
then .value.name = "something"
else . end)
假设 z
中的每个值都有一个名称 属性,您可以这样做:
$ jq --arg newname 'something' '.z[].name = $newname' input.json
对对象使用 []
将产生该对象中包含的所有值。对于这些值中的每一个,我们只是将 name
设置为新名称。
如果您需要对要更新的内容更具选择性,则必须为要更新的对象添加更多条件。一般来说,我会使用 peak 的方法,但这里有另一种方法可以使用类似于第一种方法的结构来实现,假设我们只想更新已经有 name
属性 的对象:
$ jq --arg newname 'something' '(.z[] | select(has("name")).name) = $newname' input.json
将赋值的 LHS 括在括号中很重要,我们不想在赋值之前更改上下文,否则我们将看不到其余结果。