如何使用 bash 解析内容并将其添加到 json?

如何使用 bash 解析内容并将其添加到 json?

我遵循下面 stackexchange 文章中的想法

但我在选择和添加时遇到引号问题。

这是我的示例 json 文件

{
  "options": [
    {
      "label": "22",
      "value": "2022"
    },
    {
      "label": "23",
      "value": "2023"
    }
  ]
}

这是我的测试 bash 脚本

#!/bin/bash

previous_year=$(date --date="$(date +'%Y') - 1 year" +%Y)
last_year=$((previous_year + 31))
label=$((last_year -2000))

echo ${last_year}

jq 'del(.options[]? | select(.label == \"${previous_year}\"))' temp.json
jq '.options += [{
      "label": '${label}',
      "value": '${last_year}'
    }]' temp.json

如果我使用此示例文件运行 bash 脚本,我会得到 jq: error: syntax error, Unexpected INVALID_CHARACTER (Unix shell quoting issues?) at , line 1: del(.options[]? | select(.label == "${ previous_year}"))
jq: 1 编译错误

如果我删除 " 它会运行,但找不到任何要删除的内容,因为它看起来没有引号。它还会将元素添加到数组中,但没有引号。

我该怎么做?

  • 查找带引号的元素
  • 添加带引号的元素

预期结果(我想要实现的)是

{
  "options": [
    {
      "label": "23",
      "value": "2023"
    },
    {
      "label": "53",
      "value": "2053"
    }
  ]
}

答案1

假设 shell 变量label、 、 中具有正确的值last_year,并且previous_year您想要删除数组中options具有该value值的所有条目,并添加具有该值和value 的$previous_year新条目。label$labelvalue$last_year

jq  --arg add_label "$label" \
    --arg add_value "$last_year" \
    --arg del_value "$previous_year" '
    del(.options[]? | select(.value == $del_value)) |
    .options += [{ label: $add_label, value: $add_value }]' file

这可以在一次调用中正确组合两个操作jq

该命令使用jq从您之前创建的 shell 变量中获取的值来实例化三个内部字符串变量。使用--arg从 shell 变量创建内部字符串变量可确保值被正确编码(这可以避免代码注入漏洞)。

正如在您的代码中一样,我使用.options[]?而不只是为了避免数组不存在.options[]时出现错误。options如果确实存在,则删除任何值为(具有来自 shell 变量的值的内部变量)value的条目。您尝试选择使用,但我相信这可能是一个拼写错误。$del_valueprevious_yearlabel

(可能)修改的文档将传递到下一阶段,该阶段将新元素添加到数组中options。如果该数组先前不存在,则将使用单个元素创建它。

另请注意,它jq不会进行就地编辑,这意味着您需要将上述命令的输出重定向到新名称,然后用该新文件替换原始文件。或者,使用 GNU sponge

jq ...as above... file | sponge file

(假设您的文件名为file。)

答案2

#!/bin/bash
file=temp.json
now="$(date)"
previous_year=$(date --date="$(date +'%Y') - 1 year" +%Y)
last_year=$((previous_year + 31))
label=$((last_year -2000))
echo "==============================================================================================================="
echo "| Started parsing json file at script at: $file"
echo "| Started at:                             $now"
echo "| previous year is:                       $previous_year"
echo "| last year to be at json array is:       $last_year"
echo "| label assigned to the last year :       $label"
echo "==============================================================================================================="

if cat $file | grep $previous_year
then
  jq --arg key "$previous_year" 'del(.options[] | select(.value == $key))' $file >> new.json
  jq --arg key "$label" --arg val "$last_year" '.options += [{
        "label": $key,
        "value": $val
      }]' new.json >> new2.json
  mv new2.json $file
  rm new.json
  echo "last year found and parsed"  
else
  echo "nothing to be done"
fi

now="$(date)"
echo "==============================================================================================================="
echo "| Ended script at: $now"
echo "==============================================================================================================="
´´´

相关内容