キーと値の両方が変数として転送される既存のJSONファイルに新しいキーペアを作成しようとしています。私には次のコマンドラインがあります。
jq --arg key "$key" --arg value "$value" 'getpath(path('$key')) = '$value'' "$json"
場所: $key - キー $value - 値 $json - JSON データを含むファイル
たとえば、私の値はなので、Linux CentOS
コマンドを実行すると
+ jq --arg key .operating_system.NAME --arg value 'CentOS Linux' 'getpath(path(.operating_system.NAME)) = CentOS' Linux ./servername_1648782569.json
jq: error: CentOS/0 is not defined at <top-level>, line 1:
getpath(path(.operating_system.NAME)) = CentOS
jq: 1 compile error
UPD:スクリプトが直面しているときの私のJSONデータ:
{
"operating_system": {}
}
貼り付ける値
NAME="CentOS Linux"
のソースは次のとおりです。
/etc/os-release
割り当て機能:
function assign_value ()
{
if [ -z "$1" ]
then
echo __msg_error "Key is not passed as argument."
exit 1
elif [ -z "$2" ]
then
echo __msg_error "Value is not passed as argument."
exit 1
elif [ -z "$3" ]
then
echo __msg_error "JSON file path is not passed as argument."
exit 1
fi
key="$1"
value="$2"
json="$3"
tmp=$(mktemp)
jq --arg key "$key" --arg value "$value" "getpath(path("$key")) = "$value"" "$json" > "$tmp"
mv -- "$tmp" "$json"
}
パラメータが上記の関数に渡される位置
...
if test -e /etc/os-release
then
os_release_path='/etc/os-release'
else
os_release_path='/usr/lib/os-release'
fi
. "${os_release_path}"
MAJOR_VERSION_ID=$(echo $VERSION_ID | awk -F '.' '{print $1}')
initialize_new_area "$JSON_AREA" "$JSON"
#assign_value "${JSON_AREA}.NAME" "$NAME" "$JSON"
assign_value "${JSON_AREA}.ID" "$ID" "$JSON"
assign_value "${JSON_AREA}.ID_LIKE" "$ID_LIKE" "$JSON"
assign_value "${JSON_AREA}.MAJOR_VERSION_ID" "$MAJOR_VERSION_ID" "$JSON"
...
答え1
jq
createvariablesを使用していますが、式では使用--arg
しません。jq
代わりに二重引用符を使用するため、シェル変数を式に挿入します。これは問題の一部です。
jq
文字列または有効なJSON文書以外のものとしてデータを渡すことはできません。表現する(このようなパスは.operating_system.NAME
)不可能です。代わりに、文字列が渡され、パス文で解析されます。
jq
一重引用符式に変数を使用し、指定された「キー」値を点に分割して、パス式としてjq
使用できる値に解析します。jq
jq --arg key "$key" --arg value "$value" '
setpath($key | split("."); $value)' "$json" > "$tmp"
上記の一重引用符は、シェル変数による$key
シェル拡張を防ぎます。$value
代わりに内部変数として扱われjq
(正しいエンコーディング)を使用して割り当てられた値を持ちます。--arg
jq
テスト:
$ cat file
{
"operating_system": {}
}
$ key="operating_system.release.date"
$ value="2022-04-01"
$ jq --arg key "$key" --arg value "$value" 'setpath($key|split(".");$value)' file
{
"operating_system": {
"release": {
"date": "2022-04-01"
}
}
}
この特定の方法で配列要素の設定をサポートするには、パス要素を数値に変換する必要がありますが、変換に失敗した場合は、その要素を文字列として使用するように戻す必要があります。
jq --arg key "$key" --arg value "$value" '
setpath($key | split(".") |
map(try tonumber catch null // .); $value)' file
テスト:
$ key="operating_system.dates.0"
$ value="2022-04-02"
$ jq --arg key "$key" --arg value "$value" 'setpath($key|split(".")|map(try tonumber catch null // .); $value)' file
{
"operating_system": {
"dates": [
"2022-04-02"
]
}
}