52ky 发表于 2022-5-3 11:09:40

jq 获取对象键并在一个过滤器中更改其名称

问题
我正在使用这个 JSON(更大的 JSON 代码的一部分):

group='{ "129": { "bounds": { "left": 20, "top": 20, "width": 250, "height": 200 }, " slot”:88,“userSize”:null,“stackTabs”:true,“showThumbs”:true,“showUrls”:true,“tileIcons”:true,“catchOnce”:true,“catchRules” ;: “”, “标题”: “”, “id”: 129 } }'

首先,我得到了顶级键(这里是 "129" ),它实际上可以是任何数字:

键=`回声$组| jq 'keys'` #“129”

我想将此键更改为另一个名为 nextID 的数字,该数字是从较大的 JSON 中的另一个条目获得的:

nextID=`echo $groups_meta | jq '.nextID'`#130

现在问题来了。我可以使用以下过滤器更改密钥,但在我看来它相当脆弱和复杂:

new_group=`回声 $group | jq --arg key $key --arg nextID $nextID 'with_entries( if .key | contains($key) then .key |= "$nextID" else .end)'`

您可以看到过滤器通过搜索名称来查找键。如果以后有另一个具有相同名称的键,这可能是一个问题。那是脆弱的。这种方法看起来相当复杂;我真的很想得到这个密钥(如上面的 keys )并使用它来进行更改,所有这些都在同一个过滤器中。

所以我的问题是:有没有办法把这两个部分结合起来,不用搜索就能得到钥匙?

更新

样本输入:

group='{ "129": { "bounds": { "left": 20, "top": 20, "width": 250, "height": 200 }, " slot”:88,“userSize”:null,“stackTabs”:true,“showThumbs”:true,“showUrls”:true,“tileIcons”:true,“catchOnce”:true,“catchRules” ;: “”, “标题”: “”, “id”: 129 } }'

下一个 ID=130

jq 命令:

new_group=`回声 $group | jq --arg nexID $nextID 'filter'`

预期输出:
echo $new_group
{ "130": { "bounds": { "left": 20, "top": 20, "width": 250, "height": 200 }, "slot": 88, "userSize": null, "stackTabs": true, "showThumbs": true, "showUrls": true, "tileIcons": true, "catchOnce": true, "catchRules": "", "title": "", "id": 130 } }
请注意,第一个键应该可以按位置寻址,例如“129”。如上所示,因为事先不知道数量。键 keys 的值也设置为 id 。两者都应该使用 bash 变量“130”来设置。导入jq。

更新 2

使用@jq170727's 的答案,我成功地在 $nextID 之后添加了一些值更改,但是我在将同一输入中的 .title 值更改为带空格的字符串时遇到了问题:

下一个ID

这将引发错误:
title="new title"
new_group=`echo $group | jq --arg nextID $nextID --arg title $title '(keys_unsorted|first) as $i | with_entries(if .key == $i then .key=$nextID | .value.id=$nextID | .value.title=$title else . end)'`
在 jq 命令中引用 title 变量也会产生错误。如果标题在 bash 中没有空格,则此命令有效。

我是否错过了使用包含空格的变量更新值的技巧?我应该问一个新问题吗?

回答
您的原始过滤器已关闭。这是一个做你所要求的。

(keys_unsorted|first) 作为 $i | with_entries(如果 .key == $i 则 .key=$nexID| .value.id=$nexID 否则 .end)

bash 中的交互式示例:在线试用!

您可以一次完成所有操作,而不是使用单独的调用。

例如,假设完整的 json 是
{
"group": {
    "129": {
      "bounds": { "left": 20, "top": 20, "width": 250, "height": 200 },
      "slot": 88, "userSize": null, "stackTabs": true, "showThumbs": true, "showUrls": true,
      "tileIcons": true, "catchOnce": true, "catchRules": "", "title": "", "id": 129
    }
},
"groups_meta": {
    "nextID": 130
}
}
你可以使用这个过滤器
   (.group | keys_unsorted | first) as $i
| (.groups_meta.nextID | tostring) as $n
| .group |= with_entries( if .key == $i then .key = $n | .value.id = $n else . end )
在线尝试!

这将相信从 nextID 生成的字符串不在组中。
nextID
you can add something like
| .groups_meta.nextID += 1 to the end.



页: [1]
查看完整版本: jq 获取对象键并在一个过滤器中更改其名称