Json jq在空格后截断ENV变量
尝试编写一个bash脚本来替换JSON文件中的值时,我们遇到了包含空格的环境变量问题 给定一个原始JSON文件Json jq在空格后截断ENV变量,json,bash,jq,Json,Bash,Jq,尝试编写一个bash脚本来替换JSON文件中的值时,我们遇到了包含空格的环境变量问题 给定一个原始JSON文件 { "version": "base", "myValue": "to be changed", "channelId": 0 } 我们希望运行一个命令来更新其中的一些变量,以便在运行之后: CHANNEL_ID=1701 MY_VALUE="new value" ./test.sh JSON应该如下所示: { "version": "base", "myVal
{
"version": "base",
"myValue": "to be changed",
"channelId": 0
}
我们希望运行一个命令来更新其中的一些变量,以便在运行之后:
CHANNEL_ID=1701 MY_VALUE="new value" ./test.sh
JSON应该如下所示:
{
"version": "base",
"myValue": "new value",
"channelId": 1701
}
#!/bin/sh
echo $MY_VALUE
echo $CHANNEL_ID
function replaceValue {
if [ -z $2 ]; then echo "Skipping $1"; else jq --argjson newValue \"${2}\" '. | ."'${1}'" = $newValue' build/config.json > tmp.json && mv tmp.json build/config.json; fi
}
replaceValue channelId ${CHANNEL_ID}
replaceValue myValue ${MY_VALUE}
我们的脚本目前处于如下状态:
{
"version": "base",
"myValue": "new value",
"channelId": 1701
}
#!/bin/sh
echo $MY_VALUE
echo $CHANNEL_ID
function replaceValue {
if [ -z $2 ]; then echo "Skipping $1"; else jq --argjson newValue \"${2}\" '. | ."'${1}'" = $newValue' build/config.json > tmp.json && mv tmp.json build/config.json; fi
}
replaceValue channelId ${CHANNEL_ID}
replaceValue myValue ${MY_VALUE}
在上面的例子中,所有的值都被字符串替换,字符串在空白处被截断。我们不断地在这个问题和替换完全停止工作的代码版本之间切换
这当然是扩张的问题,但我们很想弄清楚,我们如何能够:
-用字符串和值替换JSON中的值。
-在传递给脚本的字符串中使用空格。jq允许您构建新对象:
MY_VALUE=foo;
CHANNEL_ID=4
echo '{
"version": "base",
"myValue": "to be changed",
"channelId": 0
}' | jq ". | {\"version\": .version, \"myValue\": \"$MY_VALUE\", \"channelId\": $CHANNEL_ID}"
选择整个输入,并输入(|
)以构造新对象(由{}
标记)。对于版本is,从输入中选择.version
,但您可以为其他两个设置自己的值。我们使用双引号来允许Bash变量扩展,这意味着在JSON中转义双引号
您需要修改我上面的代码片段来编写脚本。使用
--arg传递变量。做:
jq --arg key "$1" --arg value "$2" '.[$key] = $value'
注:
#/bin/sh
表示这是posix shell脚本,而不是bash。使用#/bash脚本中的bin/bash
function replaceValue{
是来自ksh shell的内容。首选replaceValue(){
来声明函数
- 在脚本中使用换行符使其可读
--argjson
传递一个json格式的参数,而不是字符串。为此,请使用--arg
\“${2}\”
不引用$2
扩展-它只在字符串后面加上“
后缀。因为扩展没有被执行,所以执行了分词,这会导致在为jq
创建参数时,输入被拆分为空白
- 记住引用变量展开式
- 用于检查脚本
在jq
中没有任何意义,就像echo$(echo$(echo))
。你可以jq.|.|.|.|.|.|.|.|.|.|.|.|.
做无数次-它传递同样的东西。只要写下你想做的事情就行了
做:
@用更简单的[$key]编辑替换的“\($key)”
将环境变量导入到jq
的上下文中时,不必处理--arg
或--argjson
。它可以很好地自行读取环境。您不需要单独编写脚本,只需在调用jq
的同时设置值即可
CHANNEL_ID=1701 MY_VALUE="new value" \
jq '{"version": "base", myValue: env.MY_VALUE, channelId: env.CHANNEL_ID}' build/config.json
请注意,在上述情况下,变量不需要全局导出,而只需本地导出到jq
命令。这允许您不将多个变量导出到shell并污染环境,而只导出jq
构建所需JSON所需的变量
要将更改返回到原始文件,请执行>tmp.json&&mv tmp.json build/config.json
或更清楚地从包中下载该实用程序。如果存在,您可以将jq
的输出作为管道传输
| sponge build/config.json
newValue\“${2}\”
为什么?使用“
而不是--argjson
而不是--arg
?@KamilCuk:你不需要它,你可以直接在jq
(1)中导入环境变量,在jq中,{version:.version
可以缩写为{version}/code>(2)正如在另一个答案中指出的,这里的首字母|
毫无意义。(3)使用shell的字符串插值通常是不明智的,主要是因为它不安全,但也因为使用双引号引用jq程序需要在命令行上转义程序中的双引号。许多优点,但[$key]
比“\($key)对眼睛和手指更容易"
而且jq 1.3支持它,因此更为健壮。感谢您的详细解释,我今天学到了很多。虽然现在所有值都以字符串形式出现在我的JSON文件中。我可以通过在每个值上运行类似下面的行来修复它,我想成为一个数字,但只是想知道是否有更好的解决方案?jq.channelId |=tonumber'build/config.json>tmp.json&&mv tmp.json build/config.json
感谢您的输入。很遗憾,我认为这个解决方案不适用于我的情况,因为可能没有定义变量。尝试在这里覆盖默认值。快速尝试后,上面的代码将未指定的变量设置为null。不过,我会仔细研究。