【问题标题】:Loop through JSON file in bash script在 bash 脚本中循环遍历 JSON 文件
【发布时间】:2020-11-08 14:39:19
【问题描述】:

我有一个用户输入数据库名称的 bash 脚本,然后我的脚本需要遍历这个数据库配置文件。我的 JSON 看起来像这样:

{
    "_id":1,
    "db_name":"postgres",
    "username":"postgres_user",
    "password":"postgres_pass",
    "daily" : {
               "days_to_backup" : [1,2],
               "delete_after" : 14,
               "compressed" : true,
           "path" : "localhost"
         },
    "monthly" : {
               "days_to_backup" : [2,5,30],
               "delete_after" : 7,
               "compressed" : false,
           "path" :" localhost"
         },
    "yearly" : {
               "days_to_backup" : [100],
               "delete_after" : 14,
               "compressed" : true,
           "path" : "localhost"
          }
}
{
    "_id":2,
    "db_name":"test",
    "username":"test_user",
    "password":"test_pass",
    "daily" : {
               "days_to_backup" : [1,7],
               "delete_after" : 14,
               "compressed" : true,
           "path" : "localhost"
           },

    "monthly" : {
               "days_to_backup" : [2,5,25],
               "delete_after" : 7,
               "compressed" : false,
           "path" : "localhost"
           },

    "yearly" : {
               "days_to_backup" : [50],
               "delete_after" : 14,
               "compressed" : true,
           "path" : "localhost"
           }


}

现在,一旦用户使用特定的数据库名称运行脚本,我想遍历“days_to_backup”数字,并且每天看起来它与今天的日期相同。问题是我不知道如何获取每日/每月/yealy.days_to_backup 然后循环遍历这些天。 我试过 jq :

#! /bin/sh

#monday is first day of the week
export Today=$(date +%d)
while getopts d: flag
do
    case "${flag}" in
        d) database=${OPTARG};;


    esac
done

if jq .db_name file.json | grep $database
then
        jq 'select(.db_name=="'$database'")' file.json
        ##this one returns the whole document of the specified database
        ##loop here for daily/monthly_yearly.days_to_backup???
else
        echo "database not found"
fi

编辑:我的输入是数据库的名称(“postgres”),然后我将遍历每日/每月/每年的数组,如果数字类似于当前日期(今天是每月 8 号),那么输出将是 - 回显“今天备份”。

Edit2:对不起,我的错。对于每天,这意味着一周中的那一天,因此(1,7)是星期日和星期六,如果当前日期是星期日或星期六,我想要并回显“今天备份”。对于每月,它表示当月的某一天,所以如果我有每月 (01,08),它将回显“今天的备份”,因为今天是该月的 8 号。每年我都想从一年的第一天开始。

好的,所以我成功地遍历了数组,但现在的问题是它遍历了 2 个大对象 (id 1 + 2) 的数组

for i in $(jq -r ".daily.days_to_backup | .[]" file.json)
  do
    echo $i "im number"
  done

如何选择它只在 _id:1 / db_name: postgres 上运行?

【问题讨论】:

  • 请添加到您的问题示例输入和您想要的输出(无描述)。
  • 这是否意味着每个月的 29 日应该进行每日备份和每年的备份,而 30 日则应该进行每月备份?
  • 已编辑。当我调用脚本时,我用 -d 指定数据库的名称,然后对于每个 Daily/monthly/yearly.days_to_Backup 数组,我想检查其中的数字是否与当前日期相同。如果是,只需打印一个回显它是同一日期。
  • 你必须对date +%d 小心一点——对于个位数的日子,你会得到一个前导零,这可能会影响你的比较。
  • 你可能会发现 gron 比 jq 更容易使用

标签: bash jq


【解决方案1】:

一种有效的方法是基于使用any,例如大致如下:

jq --arg db $database --argjson Today $Today '
    select(.db_name==$db and
           any(.daily[], .monthly[], .yearly[]; . == $Today) ) 
' file.json

请注意,两个参数($database 和 $Today)都应该作为命令行参数传入,而不是使用基于 shell 的字符串插值提供。使用 --argjson 将确保 shell 变量 $Today 中的任何前导 0 都不会导致问题。

另请注意,上述查询将返回 0 个或多个值的流。您可能希望保证名称是不同的,例如通过使用 jq 内置过滤器unique(为数组定义),或在jq Cookbook 中定义的面向流的过滤器uniques

【讨论】:

  • 您能解释一下. 是如何与$Today 相等的吗?
  • 在这种情况下使用 --argjson 将确保 Today 是一个 JSON 数字。
  • 但是.是一个整体结构。
  • 不。查看builtin.jq中any/2的定义
猜你喜欢
  • 2020-01-16
  • 1970-01-01
  • 1970-01-01
  • 2014-11-19
  • 1970-01-01
  • 1970-01-01
  • 2013-09-25
  • 2012-07-25
  • 1970-01-01
相关资源
最近更新 更多