簡體   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