我遵循下面 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
$label
value
$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_value
previous_year
label
(可能)修改的文档将传递到下一阶段,该阶段将新元素添加到数组中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 "==============================================================================================================="
´´´