使用jq从变量

时间:2019-02-08 22:42:53

标签: bash jq

我想使用在Linux bash shell中使用jq指定的变量来修改以下json。

var1="red"
var2="european.flowers"
var3="european_vegetables"
var4="20"

我的json:

{
 "plants": {
  "flowers.small": {
    "colour": "",
    "age": "",
    "vegetables": {
     "root": "",
     "height": ""
    }
  }
 }
}

我想使用jq中的变量修改json:

{
 "plants": {
  "${var2}": {
    "colour": "${var1}",
    "age": "",
    "${var3}": {
     "root": "",
     "height": "${var4}"
    }
  }
 }
}

我正在尝试仅通过变量设置字段值:

命令:

cat myjson.json|jq '.plants["flowers.small"].colour = "${var1}"' -c

结果是:

{"plants":{"flowers.small":{"colour":"${var1}","age":"","vegetables":{"root":"","height":""}}}}

命令

cat myjson.json|jq --arg v "$var1" '.plants.["flowers.small"].colour = [$v]' -c

结果是:

jq: error: syntax error, unexpected '[', expecting FORMAT or QQSTRING_START (Unix shell quoting issues?) at <top-level>, line 1:
.plants.["flowers.small"].colour = $v
jq: 1 compile error

我的jq版本是:jq-1.5-1-a5b5cbe

如何重命名字段并从变量中设置键的值? 使用jq版本甚至可以做到吗?

2 个答案:

答案 0 :(得分:1)

我怀疑这与您想要的很接近:

#!/bin/bash

var1="red"
var2="european.flowers"
var3="european_vegetables"
var4="20"

jq --arg var1 "$var1" \
   --arg var2 "$var2" \
   --arg var3 "$var3" \
   --arg var4 "$var4" '
   {"${var1}": $var1, "${var2}": $var2, "${var3}": $var3, "${var4}": $var4} as $dict
   | walk( if type == "string" and $dict[.] then  $dict[.] 
           elif type=="object" then with_entries(if $dict[.key] then .key |= $dict[.] else . end)
           else . end)' template.json

这种通用方法是可以的,但是您可能需要查看jq Cookbook,以获取有关将jq用作模板引擎的建议:https://github.com/stedolan/jq/wiki/Cookbook#using-jq-as-a-template-engine

精简版本

如果您的jq支持$ARGS,则可以使用上面的简化版本:

jq --arg '${var1}' "$var1" \
   --arg '${var2}' "$var2" \
   --arg '${var3}' "$var3" \
   --arg '${var4}' "$var4" '
    $ARGS.named as $dict
    | walk( if type == "string" and $dict[.] then  $dict[.] 
            elif type=="object" then with_entries(if $dict[.key] then .key |= $dict[.] else . end)
            else . end)' template.json

答案 1 :(得分:0)

使用jq作为模板引擎

如果您不是真的需要input.json作为单独的文件,则很容易做的就是将整个模板定义为jq表达式:

var1="red"
var2="european.flowers"
var3="european_vegetables"
var4="20"
jq -n --arg var1 "$var1" --arg var2 "$var2" --arg var3 "$var3" --arg var4 "$var4" '
{
 "plants": {
  "\($var2)": {
    "colour": $var1,
    "age": "",
    "\($var3)": {
     "root": "",
     "height": $var4
    }
  }
 }
}'

作为输出发出:

{
  "plants": {
    "european.flowers": {
      "colour": "red",
      "age": "",
      "european_vegetables": {
        "root": "",
        "height": "20"
      }
    }
  }
}

或者:重命名子树

如果您确实要要重命名现有密钥,请考虑以下方法。在模板字段中使用jq变量不是强制性的,但这确实使以后更改代码更容易:

var1="red"; var2="european.flowers"; var3="european_vegetables"; var4="20"

jq --arg var1 "$var1" --arg var2 "$var2" --arg var3 "$var3" --arg var4 "$var4" '

  # set variables for the fields we expect to see in our input
  "flowers.small" as $plant_tmpl |
  "vegetables" as $cat_tmpl |

  # change things inside fields we will later rename *before* we rename those fields
  .plants[$plant_tmpl].colour = $var1 |
  .plants[$plant_tmpl][$cat_tmpl].height = $var4 |

  if $var3 == $cat_tmpl then . else
    # var3 is not "vegetables" (templated value), so we need to rename it
    .plants[$plant_tmpl][$var3] = .plants[$plant_tmpl][$cat_tmpl] |
    del(.plants[$plant_tmpl][$cat_tmpl])
  end |

  if $var2 == $plant_tmpl then . else
    .plants[$var2] = .plants[$plant_tmpl] |
    del(.plants[$plant_tmpl])
  end
' <<'EOF'
{
 "plants": {
  "flowers.small": {
    "colour": "",
    "age": "",
    "vegetables": {
     "root": "",
     "height": ""
    }
  }
 }
}
EOF