对一个JSON模板进行多项更改

时间:2017-10-27 18:12:47

标签: json bash templates jq

我目前正在使用带有1pass CLI的jq来尝试将随机生成的密码创建到安全注释中。我在设置字段时遇到问题。

这是我的两个变量。我总共需要设置8个。

section0_section_uuid="Section_0"

section1_section_uuid="Section_1"

以下是我操纵模板的命令。我首先阅读它,更改第一个标题,然后将其保存到$template。然后我将$template传递给jq

template=$(cat template.json | jq --arg uuid "$section0_section_uuid" '.sections[0].title=$uuid')

template=$($template | jq --arg uuid "$section1_section_uuid" '.sections[1].title=$uuid')

echo $template

我的文件名太长了。我不认为我正确地传递了修改后的模板变量。我需要对template.json文件进行7次修改。

编辑:

这是我试图操纵的完整模板。对我必须制作的模板进行了12次全面更改。 12个中的10个是我将生成的随机数。 12个中的剩余2个将是生成的用户名。

{
  "fields": [],
  "sections": [
    {
      "fields": [
        {
          "k": "concealed",
          "n": "[CHANGE_ME]",
          "t": "ROOT_USER_PASS",
          "v": "[CHANGE_ME]"
        },
        {
          "k": "concealed",
          "n": "[CHANGE_ME]",
          "t": "DEV_USER_PASS",
          "v": "[CHANGE_ME]"
        }
      ],
      "name": "Section_[CHANGE_ME]",
      "title": "Container SSH"
    },
    {
      "fields": [
        {
          "k": "string",
          "n": "[CHANGE_ME]",
          "t": "placeholdertext",
          "v": "[CHANGE_ME_LETTERS]"
        },
        {
          "k": "string",
          "n": "[CHANGE_ME]",
          "t": "placeholdertext",
          "v": "[CHANGE_ME_LETTERS]"
        },
        {
          "k": "concealed",
          "n": "[CHANGE_ME]",
          "t": "placeholdertext",
          "v": "[CHANGE_ME]"
        }
      ],
      "name": "Section_[CHANGE_ME]",
      "title": "MySQL"
    }
  ]
}

3 个答案:

答案 0 :(得分:2)

为什么不将模板设为实际的jq过滤器,而不是要修改的JSON blob?

template.jq的内容将是

{
  sections: [
    { title: $t1 },
    { title: $t2 },
    { title: $t3 },
    { title: $t4 },
    { title: $t5 },
    { title: $t6 },
    { title: $t7 },
    { title: $t8 }
  ]
}

那么你的命令就是

$ jq -n --arg t1 foo --arg t2 bar ... -f template.jq
{
  "sections": [
    {
      "title": "foo"
    },
    {
      "title": "bar"
    },
    ...
  ]
}

这样做的一个好处是你不会意外忘记一个价值;如果您为所有8个变量提供定义,jq只能处理过滤器。

答案 1 :(得分:0)

这是一个解决方案,它使用jq从bash变量构建合法的json数组,然后使用该数组和第二个jq调用将变量替换为相应位置的模板:

#!/bin/bash

# example template
template='{
  "sections": [
    { "title": "x" },
    { "title": "y" }
  ]
}'

# bash variables 
section0_section_uuid="Section_0"
section1_section_uuid="Section_1"

# put into json array with jq
uuids=$(jq -MRn '[inputs]' <<EOF
$section0_section_uuid
$section1_section_uuid
EOF)

# substitute json array into template
jq -M --argjson uuids "$uuids" '
  reduce ($uuids|keys[]) as $k (.; .sections[$k].title = $uuids[$k])
' <<< "$template"

示例输出

{
  "sections": [
    {
      "title": "Section_0"
    },
    {
      "title": "Section_1"
    }
  ]
}

Try it online!

这是修订问题的一部分的解决方案,其通过用来自由bash变量构造的对象的相应值替换模板中的叶值并通过--argjson传递给jq来工作。如果为替换值选择更合适的名称然后[CHANGE_ME][CHANGE_ME_LETTERS]

,则应该直截了当地概括为完整模板
#!/bin/bash

# example template
template='{
  "fields": [],
  "sections": [ {
      "fields": [ {
          "k": "concealed",
          "n": "[SSH_ROOT_USER_N]",
          "t": "ROOT_USER_PASS",
          "v": "[SSH_ROOT_USER_V]"
      } ]
  } ]
}'

# bash variables 
SSH_ROOT_USER_N="abcd"
SSH_ROOT_USER_V="efgh"

# put into json object with jq
vars=$(jq -M . <<EOF
{
 "[SSH_ROOT_USER_N]": "$SSH_ROOT_USER_N",
 "[SSH_ROOT_USER_V]": "$SSH_ROOT_USER_V"
}
EOF)

# substitute variables into template
jq -M --argjson vars "$vars" '
reduce (tostream|select(length==2)) as [$p,$v] (
    {}
  ; setpath($p;if $v|type!="string" then . else $vars[$v]//$v end)
)
' <<< "$template"

示例输出

{
  "fields": {},
  "sections": [
    {
      "fields": [
        {
          "k": "concealed",
          "n": "abcd",
          "t": "ROOT_USER_PASS",
          "v": "efgh"
        }
      ]
    }
  ]
}

Try it online!

答案 2 :(得分:0)

以下解决问题的方法类似于@ jq170727(特别是,jq程序对“section_uuid”变量的 number 以及名称都是不可知的模板变量),但只需要一次jq调用(而不是三次)。

另一个显着差异是reduce用于避免与使用tostream相关的惩罚。一个小的区别是inputs用于避免同时读取“section_uuid”变量值。

  

注意:下面定义的fillin函数应足以用于基本模板。

在下文中,假设“模板”文件名为template.json

template.jq

# input: a JSON entity defining a template;
# vars: a JSON object defining TEMPLATEVARIABLE-VALUE pairs
def fillin(vars):
  reduce paths as $p (.;
    getpath($p) as $v
    | if $v|type == "string" and vars[$v] 
      then setpath($p; vars[$v])
      else . 
      end);

reduce inputs as $line ({i:0, value:$template};
  (.value.sections[.i].title |= $line)
  | .i +=1)
| .value
| fillin($vars)

脚本

#!/bin/bash

### Set the bash variables - as many as needed

section0_section_uuid="Section_0"
section1_section_uuid="Section_1"

ROOT_USER_PASS=RUP
DEV_USER_PASS=DUP

### Preparations for calling jq
vars=$(cat<<EOF
{
 "ROOT_USER_PASS": "$ROOT_USER_PASS",
 "DEV_USER_PASS": "$DEV_USER_PASS"
}
EOF
)

cat << EOF | jq -nR --argfile template template.json --argjson vars "$vars" -f template.jq
$section0_section_uuid
$section1_section_uuid
EOF

输出

使用(扩展)示例模板,输出为:

{
  "fields": [],
  "sections": [
    {
      "fields": [
        {
          "k": "concealed",
          "n": "[CHANGE_ME]",
          "t": "RUP",
          "v": "[CHANGE_ME]"
        },
        {
          "k": "concealed",
          "n": "[CHANGE_ME]",
          "t": "DUP",
          "v": "[CHANGE_ME]"
        }
      ],
      "name": "Section_[CHANGE_ME]",
      "title": "Section_0"
    },
    {
      "fields": [
        {
          "k": "string",
          "n": "[CHANGE_ME]",
          "t": "placeholdertext",
          "v": "[CHANGE_ME_LETTERS]"
        },
        {
          "k": "string",
          "n": "[CHANGE_ME]",
          "t": "placeholdertext",
          "v": "[CHANGE_ME_LETTERS]"
        },
        {
          "k": "concealed",
          "n": "[CHANGE_ME]",
          "t": "placeholdertext",
          "v": "[CHANGE_ME]"
        }
      ],
      "name": "Section_[CHANGE_ME]",
      "title": "Section_1"
    }
  ]
}