繁体   English   中英

当路径和值是 env 变量时在 jq 中设置值未按预期工作(bash)

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM