使用jq修改JSON

时间:2017-01-06 10:12:42

标签: json bash jq

我想使用Linux命令行修改JSON文件。

我尝试了以下步骤:

[root@localhost]# INPUT="dsa"
[root@localhost]# echo $INPUT
dsa
[root@localhost]# CONF_FILE=test.json
[root@localhost]# echo $CONF_FILE
test.json
[root@localhost]# cat $CONF_FILE
{
  "global" : {
    "name" : "asd",
    "id" : 1
  }
}
[root@localhost]# jq -r '.global.name |= '""$INPUT"" $CONF_FILE > tmp.$$.json && mv tmp.$$.json $CONF_FILE
jq: error: dsa/0 is not defined at <top-level>, line 1:
.global.name |= dsa
jq: 1 compile error

期望的输出:

[root@localhost]# cat $CONF_FILE
    {   "global" : {
    "name" : "dsa",
    "id" : 1   } }

3 个答案:

答案 0 :(得分:4)

您唯一的问题是传递给jq的脚本引用错误。

在您的特定情况下,使用带有嵌入式\ - 转义"实例的单个双引号字符串可能最简单:

jq -r ".global.name = \"$INPUT\"" "$CONF_FILE" > tmp.$$.json && mv tmp.$$.json "$CONF_FILE"

但是,一般来说, chepner's helpful answer显示了一种更强大的替代方法,可直接在脚本中嵌入shell变量引用:使用 --arg选项传递一个值作为jq 变量允许单引号脚本,这是首选,因为它避免了对shell扩展的元素的混淆前面并且不需要转义应该传递给$的{​​{1}}个实例。

此外:

至于为什么你的报价不起作用

=由以下令牌组成:

  • 字符串文字'.global.name |= '""$INPUT""(由于单引号)
  • 字符串文字.global.name |= - 即空字符串 - 在""看到脚本之前,shell将删除引号
  • 对变量jq未加引号引用(使其值受到分词和通配)的影响。
  • 文字$INPUT的另一个例子。

使用您的示例值,""最终看到以下字符串作为其脚本:

jq

正如您所看到的,双引号丢失,导致.global.name |= dsa jq解释为函数名称而不是字符串文字,因为没有传递任何参数到(不存在的)函数dsadsa的错误消息将其称为jq - 一个没有(dsa/0)参数的函数。

答案 1 :(得分:4)

使用--arg选项传递值会更简单,更安全:

jq -r --arg newname "$INPUT" '.global.name |= $newname' "$CONF_FILE"

这确保使用$INPUT的确切值并引用为JSON值。

答案 2 :(得分:1)

jq与直接过滤器一起使用,应该为您完成。

.global.name = "dsa"

jq '.global.name = "dsa"' json-file
{
  "global": {
    "name": "dsa",
    "id": 1
  }
}

您可以使用json过滤器here