Bash 使用jq从变量更改json对象和字段值
我想使用jq在LinuxBashShell中指定的变量修改以下jsonBash 使用jq从变量更改json对象和字段值,bash,jq,Bash,Jq,我想使用jq在LinuxBashShell中指定的变量修改以下json var1="red" var2="european.flowers" var3="european_vegetables" var4="20" 我的json: { "plants": { "flowers.small": { "colour": "", "age": "", "vegetables": { "root": "", "height": "" } }
var1="red"
var2="european.flowers"
var3="european_vegetables"
var4="20"
我的json:
{
"plants": {
"flowers.small": {
"colour": "",
"age": "",
"vegetables": {
"root": "",
"height": ""
}
}
}
}
我想使用jq中的变量修改json:
{
"plants": {
"${var2}": {
"colour": "${var1}",
"age": "",
"${var3}": {
"root": "",
"height": "${var4}"
}
}
}
}
我正试图从变量中设置字段值:
命令:
cat myjson.json|jq '.plants["flowers.small"].colour = "${var1}"' -c
结果是:
{"plants":{"flowers.small":{"colour":"${var1}","age":"","vegetables":{"root":"","height":""}}}}
jq: error: syntax error, unexpected '[', expecting FORMAT or QQSTRING_START (Unix shell quoting issues?) at <top-level>, line 1:
.plants.["flowers.small"].colour = $v
jq: 1 compile error
命令:
cat myjson.json|jq --arg v "$var1" '.plants.["flowers.small"].colour = [$v]' -c
结果是:
{"plants":{"flowers.small":{"colour":"${var1}","age":"","vegetables":{"root":"","height":""}}}}
jq: error: syntax error, unexpected '[', expecting FORMAT or QQSTRING_START (Unix shell quoting issues?) at <top-level>, line 1:
.plants.["flowers.small"].colour = $v
jq: 1 compile error
jq:error:syntax error,意外的“[”,需要格式或QQSTRING_START(Unix shell引用问题?),第1行:
.植物。[“花.小”]。颜色=$v
jq:1编译错误
我的jq版本是:jq-1.5-1-a5b5cbe
如何重命名字段并从变量中为键设置值?
使用jq版本甚至可以做到这一点吗?使用jq
作为模板引擎
如果您真的不需要将input.json
作为一个单独的文件,那么简单的做法是将整个模板定义为一个jq表达式:
var1="red"
var2="european.flowers"
var3="european_vegetables"
var4="20"
jq -n --arg var1 "$var1" --arg var2 "$var2" --arg var3 "$var3" --arg var4 "$var4" '
{
"plants": {
"\($var2)": {
"colour": $var1,
"age": "",
"\($var3)": {
"root": "",
"height": $var4
}
}
}
}'
作为输出发射:
{
"plants": {
"european.flowers": {
"colour": "red",
"age": "",
"european_vegetables": {
"root": "",
"height": "20"
}
}
}
}
或者:重命名子树
如果您真的想重命名现有的密钥,请考虑下面的方法。使用模板字段的JQ变量不是强制性的,但它确实更容易在以后更改代码:
var1="red"; var2="european.flowers"; var3="european_vegetables"; var4="20"
jq --arg var1 "$var1" --arg var2 "$var2" --arg var3 "$var3" --arg var4 "$var4" '
# set variables for the fields we expect to see in our input
"flowers.small" as $plant_tmpl |
"vegetables" as $cat_tmpl |
# change things inside fields we will later rename *before* we rename those fields
.plants[$plant_tmpl].colour = $var1 |
.plants[$plant_tmpl][$cat_tmpl].height = $var4 |
if $var3 == $cat_tmpl then . else
# var3 is not "vegetables" (templated value), so we need to rename it
.plants[$plant_tmpl][$var3] = .plants[$plant_tmpl][$cat_tmpl] |
del(.plants[$plant_tmpl][$cat_tmpl])
end |
if $var2 == $plant_tmpl then . else
.plants[$var2] = .plants[$plant_tmpl] |
del(.plants[$plant_tmpl])
end
' <<'EOF'
{
"plants": {
"flowers.small": {
"colour": "",
"age": "",
"vegetables": {
"root": "",
"height": ""
}
}
}
}
EOF
var1=“红色”var2=“欧洲花卉”var3=“欧洲蔬菜”var4=“20”
jq--arg var1“$var1”--arg var2“$var2”--arg var3“$var3”--arg var4“$var4”'
#为我们希望在输入中看到的字段设置变量
“花.小”如$plant\u tmpl|
“蔬菜”作为$cat_tmpl|
#更改字段内的内容,我们稍后将重命名*然后*重命名这些字段
.plants[$plant\u tmpl].颜色=$var1|
.plants[$plant\u tmpl][$cat\u tmpl]。高度=$var4|
如果$var3==$cat\u tmpl,则为.else
#var3不是“蔬菜”(模板值),所以我们需要重命名它
.plants[$plant\u tmpl][$var3]=.plants[$plant\u tmpl][$cat\u tmpl]|
del(.plants[$plant\u tmpl][$cat\u tmpl])
结束|
如果$var2==$plant\u tmpl,则为.else
.plants[$var2]=.plants[$plant\u tmpl]|
del(.plant[$plant\u tmpl])
结束
“我怀疑这与你想要的非常接近:
#!/bin/bash
var1="red"
var2="european.flowers"
var3="european_vegetables"
var4="20"
jq --arg var1 "$var1" \
--arg var2 "$var2" \
--arg var3 "$var3" \
--arg var4 "$var4" '
{"${var1}": $var1, "${var2}": $var2, "${var3}": $var3, "${var4}": $var4} as $dict
| walk( if type == "string" and $dict[.] then $dict[.]
elif type=="object" then with_entries(if $dict[.key] then .key |= $dict[.] else . end)
else . end)' template.json
这种通用方法是可以的,但您可能希望查看jq食谱,以了解有关使用jq作为模板引擎的建议:
精简版
如果您的jq支持$ARGS
,那么您可以使用上述的简化版本:
jq --arg '${var1}' "$var1" \
--arg '${var2}' "$var2" \
--arg '${var3}' "$var3" \
--arg '${var4}' "$var4" '
$ARGS.named as $dict
| walk( if type == "string" and $dict[.] then $dict[.]
elif type=="object" then with_entries(if $dict[.key] then .key |= $dict[.] else . end)
else . end)' template.json
仅供参考,避免将输入文件名直接传递给jq
或使用更有效。我使用cat只是为了在tryping时为管道键入便利,谢谢你的建议。对我来说,如何处理json并不重要,我只想将jq作为处理json的组件传递的字符串不太容易出错。