【发布时间】:2015-11-05 20:33:51
【问题描述】:
我正在尝试使用 bash/shell 脚本中的 jq <map> 函数修改嵌套的 JSON 对象;类似于 this blog entry 的东西,但试图将此处的示例调整为嵌套对象。
返回的JSON要修改如下:
{
"name": "vendor-module",
"dependencies": {
"abc": {
"from": "abc@2.4.0",
"resolved": "https://some.special.url",
"version": "2.4.0"
},
"acme": {
"from": "acme@1.2.3",
"resolved": "<CHANGE_THIS>",
"version": "1.2.3"
}
}
}
这将是我的尝试:
modules="`node -pe 'JSON.parse(process.argv[1]).dependencies.$dependency' \
"$(cat $wrapped)"`"
version="1.2.3"
resolved="some_url"
cat OLD.json |
jq 'to_entries |
map(if .dependencies[0].$module[0].from == "$module@$version"
then . + {"resolved"}={"$resolved"}
else .
end
) |
from_entries' > NEW.json
显然这不起作用。当我运行脚本时,NEW.json 被创建但没有修改或返回错误。如果我不针对嵌套对象(例如,"name": "vendor-module"),脚本将按预期工作。我确信有一种方法可以使用本机 bash 和 jq ..??任何帮助(通过适当的转义)将不胜感激。
更新:
感谢Charles Duffy's answer 的帮助,以及他使用sponge 的建议,适合我的解决方案是:
jq --arg mod "acme" --arg resolved "Some URL" \
'.dependencies[$mod].resolved |= $resolved' \
OLD.json | sponge OLD.json
【问题讨论】:
-
“acme”的“from”后面需要一个逗号,这样才能成为有效的 JSON,顺便说一句。
-
等一下。您的输入变量中有
modules——如果您已经知道需要修改acme,而不是abc,为什么还要查看from和version? -
错字-Thnx。我快速输入了这个作为示例 - 我不想用一堆不相关的代码污染问题。
-
顺便说一句,我强烈建议逐步构建这种东西。如果您正在查看
jq '.dependencies | to_entries'的输出,那将向您显示您需要使用的数据结构类型(.value下的内容和.dependencies在当前范围内不可见)。 -
另外,我强烈建议避免不必要地使用
cat;以cat somefile | ...提供输入的程序只得到一个不可逆的管道,而以... <somefile提供输入的程序有一个正确的、可查找的文件描述符;它既更高效(总是因为缺少管道,但如果你正在实现的内容允许更少的内存使用、更好的并行化或其他算法改进(当能够寻求),那么它更灵活)和更灵活。