英文:
bash & jq: add attribute with object value
问题
以下是翻译好的部分:
"我正在寻找一种方法将具有JSON对象值的新属性添加到现有的JSON文件中。
我的当前脚本:"
if [ ! -f "$src_file" ]; then
echo "源文件 $src_file 不存在"
exit 1
fi
if [ ! -f "$dst_file" ]; then
echo "目标文件 $dst_file 不存在"
exit 1
fi
if ! jq '.devDependencies' "$src_file" >/dev/null 2>&1; then
echo "源文件 $src_file 中不存在键 'devDependencies'"
exit 1
fi
dev_dependencies=$(jq '.devDependencies' "$src_file" | xargs )
# 从源文件提取数据
data=$(cat $src_file)
# 添加新的键值对
data=$(echo $data | jq --arg key "devDependencies" --arg value "$dev_dependencies" '. + {($key): ($value)}')
# 将数据写入目标文件
echo $data > $dst_file
"它正在工作,但$dev_dependencies
中的devDependencies
值被写为字符串:
"devDependencies": "{ @nrwl/esbuild: 15.6.3, @nrwl/eslint-pl[...]
。
如何将其写为原始JSON?"
英文:
I'm looking for a solution to add a new attribute with a JSON object value into an existing JSON file.
My current script:
if [ ! -f "$src_file" ]; then
echo "Source file $src_file does not exists"
exit 1
fi
if [ ! -f "$dst_file" ]; then
echo "Destination file $dst_file does not exists"
exit 1
fi
if ! jq '.devDependencies' "$src_file" >/dev/null 2>&1; then
echo "The key "devDependencies" does not exists into source file $src_file"
exit 1
fi
dev_dependencies=$(jq '.devDependencies' "$src_file" | xargs )
# Extract data from source file
data=$(cat $src_file)
# Add new key-value
data=$(echo $data | jq --arg key "devDependencies" --arg value "$dev_dependencies" '. + {($key): ($value)}')
# Write data into destination file
echo $data > $dst_file
It's working but the devDependencies
value from $dev_dependencies
is wrote as string:
"devDependencies": "{ @nrwl/esbuild: 15.6.3, @nrwl/eslint-pl[...]"
.
How can I write it as raw JSON ?
答案1
得分: 2
我认为你想要使用 --argjson
选项而不是 --arg
。比较一下:
$ jq --arg k '{"foo": "bar"}' -n '{x: $k}'
{
"x": "{\"foo\": \"bar\"}"
}
与
$ jq --argjson k '{"foo": "bar"}' -n '{x: $k}'
{
"x": {
"foo": "bar"
}
}
英文:
I think you want the --argjson
option instead of --arg
. Compare
$ jq --arg k '{"foo": "bar"}' -n '{x: $k}'
{
"x": "{\"foo\": \"bar\"}"
}
with
$ jq --argjson k '{"foo": "bar"}' -n '{x: $k}'
{
"x": {
"foo": "bar"
}
}
答案2
得分: 1
--arg
会创建一个字符串变量。使用 --argjson
将值解析为 JSON(可以是对象、数组或数字)。
从文档中得知:
--arg name value
:此选项将一个值传递给 jq 程序作为预定义变量。
如果你使用--arg foo bar
运行 jq,那么$foo
将在程序中可用,并具有值"bar"
。请注意,value
将被视为字符串,因此--arg foo 123
将绑定$foo
到"123"
。
命名参数也可作为
$ARGS.named
在 jq 程序中使用。
--argjson name JSON-text
:此选项将一个 JSON 编码的值传递给 jq 程序作为预定义变量。如果你使用
--argjson foo 123
运行 jq,那么 $foo 将在程序中可用,并具有值123
。
注意,你不需要多次调用 jq、xargs、命令替代或变量(不要忘记在扩展时引用所有变量)。
要 "合并" 两个文件的内容,使用 jq 读取两个文件并让 jq 完成工作。这样可以避免在 jq 和 shell 上下文之间跳转产生的所有复杂情况。只需要一行代码:
jq --slurpfile deps "$dep_file" '. + { devDependencies: $deps[0].devDependencies }' "$source_file" > "$dest_file"
或者
jq --slurpfile deps "$dep_file" '. + ($deps[0]|{devDependencies})' "$source_file" > "$dest_file"
或者(仍然是一行代码):
jq --slurpfile deps "$dev_file" '.devDependencies = $deps[0].devDependencies' "$source_file" > "$dest_file"
此答案提醒了我非常有用的 input
过滤器,它可以使程序更短,因为它避免了使用变量:
jq '. + (input|{devDependencies})' "$source_file" "$dep_file" > "$dest_file"
英文:
--arg
will create a string variable. Use --argjson
to parse the value as JSON (can be object, array or number).
From the docs:
> ##### --arg name value
:
>
> This option passes a value to the jq program as a predefined variable.
> If you run jq with --arg foo bar
, then $foo
is available in the
> program and has the value "bar"
. Note that value
will be treated as a
> string, so --arg foo 123
will bind $foo
to "123"
.
>
> Named arguments are also available to the jq program as $ARGS.named
.
>
> ##### --argjson name JSON-text
:
>
> This option passes a JSON-encoded value to the jq program as a
> predefined variable. If you run jq with --argjson foo 123
, then $foo
> is available in the program and has the value 123
.
Note that you don't need multiple invocations of jq, xargs, command substitution or variables (don't forget to quote all your variables when expanding).
To "merge" the contents of two files, read both files with jq and let jq do the work. This avoids all the complications that arise from jumping between jq and shell context. A single line is all that's needed:
jq --slurpfile deps "$dep_file" '. + { devDependencies: $deps[0].devDependencies }' "$source_file" > "$dest_file"
or
jq --slurpfile deps "$dep_file" '. + ($deps[0]|{devDependencies})' "$source_file" > "$dest_file"
alternatively (still a one-liner):
jq --slurpfile deps "$dev_file" '.devDependencies = $deps[0].devDependencies' "$source_file" > "$dest_file"
peak's answer here reminded me of the very useful input
filter, which can make the program even shorter as it avoids the variable:
jq '. + (input|{devDependencies})' "$source_file" "$dep_file" > "$dest_file"
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论