简体   繁体   English

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

[英]Setting a value in jq when path and value are env variables is not working as expected (bash)

I want to set a value in a JSON nested object using jq from a shell script.我想使用 shell 脚本中的 jq 在 JSON 嵌套对象中设置一个值。 If I use explicit values, it sets the JSON value as expected.如果我使用显式值,它会按预期设置 JSON 值。 But when I use variables, it adds (if strangely) a new key/value instead.但是当我使用变量时,它会添加(如果奇怪的话)一个新的键/值。

The end goal is to set a key's value in arbitrary JSON given an arbitrary, jp-appropriate, explicit path.最终目标是在给定任意、适合 jp 的显式路径的情况下以任意 JSON 设置键的值。 No selecting/matching required.无需选择/匹配。 Let's also assume all values are Strings.我们还假设所有值都是字符串。 I get diff between --args and --argsjson.我得到--args 和--argsjson 之间的差异。

But let's start with the simple.但让我们从简单的开始。 Here is my test:这是我的测试:

echo $JSON
{
    "make" : "ford",
    "model" : "ranger",
    "year" : "2020"
    "options" : {
        "cylinders" : "v6"
        "cab" : "true"
    }
}

Let's say I want to set options.cylinders = "v4"假设我想设置options.cylinders = "v4"
This works:这有效:

echo $JSON | jq 'options.cylinders = "v4"'

This works as well:这也有效:

echo $JSON | jq --arg value "v4" '.options.cylinders = $value'

Let's replace value with variable.让我们用变量替换值。 This works.这行得通。

cyl="v4"
echo $JSON | jq --arg value "$cyl" '.options.cylinders = $value'

Let's replace the path with variable.让我们用变量替换路径。 It complains, but just to let you know where I've been:它抱怨,但只是为了让你知道我去过哪里:

cyl="v4"
path="options.cylinder"
echo $JSON | jq --arg path "$path" --arg value "$cyl" '.$path = $value'

That throws error, but it is corrected by:这会引发错误,但可以通过以下方式纠正:

cyl="v4"
path="options.cylinder"
echo $JSON | jq --arg path "$path" --arg value "$cyl" '.[$path] = $value'

Now you would think the former would work.现在你会认为前者会起作用。 It succeeds but it adds the value with the entire path as key, instead of setting it as if it where the path.它成功了,但是它将整个路径作为键添加了值,而不是将其设置为路径所在的位置。 The result is:结果是:

{
    "make" : "ford",
    "model" : "ranger",
    "year" : "2020"
    "options" : {
        "cylinders" : "v6"
        "cab" : "true"
    }
    "options.cylinders" : "v4"
}

I have also tried using the path() function, passing it an bash array.我也尝试过使用 path() 函数,将它传递给一个 bash 数组。 This does not work either.这也不起作用。

cyl="v4"
path=(".", "options", "cylinders")
echo "${JSON}" | jq --arg key $path --arg value "${cyl}" 'path($key; $value)'

I get:我得到:

jq: error: path/2 is not defined at <top-level>, line 1:
path($key; $value)
jq: 1 compile error

If I remove the "."如果我删除“。” from the path, it just moves up the error:从路径中,它只是向上移动错误:

jq: error: path/1 is not defined at <top-level>, line 1:

I have read all the doc.我已阅读所有文档。 I am sure I have tried other things, but I'm stumped at this point.我确信我已经尝试过其他的东西,但我在这一点上被难住了。 So...what am I missing here?那么......我在这里错过了什么? Close?关? Ideas?想法?

Credits to @pmf so making it a wiki感谢@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) sets the value at path with path elements as an array. setpath(path_array; value)将路径元素的值设置为数组。

So the $path string is: / divided by its .所以$path字符串是: /除以它的. dots, to turn it into an array.点,把它变成一个数组。

Lets demo this:让我们演示一下:

jq -n '"options.cylinders" / "."'

turns the string above into an array suitable for creating a path from the dot delimited string:将上面的字符串转换为适合从点分隔字符串创建路径的数组:

[
  "options",
  "cylinders"
]

So when it runs:所以当它运行时:

setpath("options.cylinders" / "."; "v4")

it expands into:它扩展为:

setpath(["options","cylinders"]; "v4")

which is exactly the same as static path value assignment:这与静态路径值分配完全相同:

.options.cylinders = "v4"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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