Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Json jq在空格后截断ENV变量_Json_Bash_Jq - Fatal编程技术网

Json jq在空格后截断ENV变量

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

尝试编写一个bash脚本来替换JSON文件中的值时,我们遇到了包含空格的环境变量问题

给定一个原始JSON文件

{
  "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。不过,我会仔细研究。