[英]Assigning jq output to bash array when json value contains spaces
[英]Setting a value in jq when path and value are env variables is not working as expected (bash)
我想使用 shell 脚本中的 jq 在 JSON 嵌套对象中设置一个值。 如果我使用显式值,它会按预期设置 JSON 值。 但是当我使用变量时,它会添加(如果奇怪的话)一个新的键/值。
最终目标是在给定任意、适合 jp 的显式路径的情况下以任意 JSON 设置键的值。 无需选择/匹配。 我们还假设所有值都是字符串。 我得到--args 和--argsjson 之间的差异。
但让我们从简单的开始。 这是我的测试:
echo $JSON
{
"make" : "ford",
"model" : "ranger",
"year" : "2020"
"options" : {
"cylinders" : "v6"
"cab" : "true"
}
}
假设我想设置options.cylinders = "v4"
这有效:
echo $JSON | jq 'options.cylinders = "v4"'
这也有效:
echo $JSON | jq --arg value "v4" '.options.cylinders = $value'
让我们用变量替换值。 这行得通。
cyl="v4"
echo $JSON | jq --arg value "$cyl" '.options.cylinders = $value'
让我们用变量替换路径。 它抱怨,但只是为了让你知道我去过哪里:
cyl="v4"
path="options.cylinder"
echo $JSON | jq --arg path "$path" --arg value "$cyl" '.$path = $value'
这会引发错误,但可以通过以下方式纠正:
cyl="v4"
path="options.cylinder"
echo $JSON | jq --arg path "$path" --arg value "$cyl" '.[$path] = $value'
现在你会认为前者会起作用。 它成功了,但是它将整个路径作为键添加了值,而不是将其设置为路径所在的位置。 结果是:
{
"make" : "ford",
"model" : "ranger",
"year" : "2020"
"options" : {
"cylinders" : "v6"
"cab" : "true"
}
"options.cylinders" : "v4"
}
我也尝试过使用 path() 函数,将它传递给一个 bash 数组。 这也不起作用。
cyl="v4"
path=(".", "options", "cylinders")
echo "${JSON}" | jq --arg key $path --arg value "${cyl}" 'path($key; $value)'
我得到:
jq: error: path/2 is not defined at <top-level>, line 1:
path($key; $value)
jq: 1 compile error
如果我删除“。” 从路径中,它只是向上移动错误:
jq: error: path/1 is not defined at <top-level>, line 1:
我已阅读所有文档。 我确信我已经尝试过其他的东西,但我在这一点上被难住了。 那么......我在这里错过了什么? 关? 想法?
感谢@pmf,所以让它成为一个维基
#!/bin/sh
# Sets the source JSON in a shell variable
json='{
"make": "ford",
"model": "ranger",
"year": "2020",
"options": {
"cylinders": "v6",
"cab": "true"
}
}'
# Parameters to modify the source JSON
path='options.cylinders'
cyl='v4'
# Process with jq
jq \
--null-input \
--argjson json "$json" \
--arg path "$path" \
--arg value "$cyl" \
'$json | setpath($path / "."; $value)'
setpath(path_array; value)
将路径元素的值设置为数组。
所以$path
字符串是: /
除以它的.
点,把它变成一个数组。
让我们演示一下:
jq -n '"options.cylinders" / "."'
将上面的字符串转换为适合从点分隔字符串创建路径的数组:
[
"options",
"cylinders"
]
所以当它运行时:
setpath("options.cylinders" / "."; "v4")
它扩展为:
setpath(["options","cylinders"]; "v4")
这与静态路径值分配完全相同:
.options.cylinders = "v4"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.