【问题标题】:jq: extract value based on different (calculated) valuejq:根据不同的(计算的)值提取值
【发布时间】:2017-08-15 19:27:02
【问题描述】:

我正在尝试将一个非常大的 json 文件(来自aws rds describe-db-snapshots 的 AWS 输出)过滤成一个快照列表以供删除。

最终的快照列表应早于 60 天。我可以通过他们的SnapshotCreateTime 辨别他们的年龄,但我需要他们的DBSnapshotIdentifier 值才能删除他们。

为了 SO 目的,大大简化了,下面是 input.json 文件。

{
  "Engine": "postgres",
  "SnapshotCreateTime": "2017-08-22T16:35:42.302Z",
  "AvailabilityZone": "us-east-1b",
  "DBSnapshotIdentifier": "alex2-20170822-0108-bkup",
  "AllocatedStorage": 5
}
{
  "Engine": "postgres",
  "SnapshotCreateTime": "2017-06-02T16:35:42.302Z",
  "AvailabilityZone": "us-east-1a",
  "DBSnapshotIdentifier": "alex-dbs-16opfr84gq4h9-snapshot-rtsmdbinstance-fr84gq4h9",
  "AllocatedStorage": 5
}
{
  "Engine": "postgres",
  "SnapshotCreateTime": "2017-04-22T16:35:42.302Z",
  "AvailabilityZone": "us-east-1a",
  "DBSnapshotIdentifier": "alex3-20170422-update",
  "AllocatedStorage": 5
}

我知道select,但据我所知,它无法处理单行中时间比较所需的数学运算。我想我需要扩展到 bash,所以我一直在搞乱以下(笨拙的)解决方法。它不起作用,但我想我会把它作为努力的证明。

THEN=$(date +'%Y%m%d' -d "`date`-60days")

while IFS= read -r i
    do
        awsDate=$(jq -r '.SnapshotCreateTime' < $i) // get time
        snapDate=$(date -d $awsDate +'%Y%m%d') //convert to correct format

        if [ $snapDate -gt $THEN ] //compare times
        then
            // something to copy the ID

        fi

    done < input.json

在这种情况下,我会寻找

的输出
alex-dbs-16opfr84gq4h9-snapshot-rtsmdbinstance-fr84gq4h9
alex3-20170422-update

【问题讨论】:

  • 次要 JSON 问题:在每个 "AllocatedStorage": 5, 键/值对中,5 后面不应有逗号。
  • @jq170727 感谢您发现这一点,这是简化时的错误,不在真实数据中。已编辑!

标签: json bash date select jq


【解决方案1】:

这是一个全 jq 解决方案(即不依赖于调用 date 命令的解决方案)。您可能想尝试一种变体,例如使用--arg等命令行选项之一传递某种形式的日期。

jq 目前还不太了解 SnapshotCreateTime 格式;这就是调用sub 的地方:

def ago(days): now - (days*24*3600);

select(.SnapshotCreateTime | sub("\\.[0-9]*";"") < (ago(60) | todate))
| .DBSnapshotIdentifier

修复示例输入使其成为有效 JSON 后,输出将是:

"alex-dbs-16opfr84gq4h9-snapshot-rtsmdbinstance-fr84gq4h9"
"alex3-20170422-update"

要去掉引号,请使用 -r 命令行选项。

【讨论】:

    【解决方案2】:

    这是一个定义过滤函数的解决方案,它使用 selectsubfromdatenow

    def too_old:
        select(   .SnapshotCreateTime
                | sub("[.][0-9]+Z";"Z")   # remove fractional seconds
                | fromdate                # convert to unix time
                | now - .                 # convert to age in seconds
                | . >  (86400 * 60)       # true if older than 60 days in seconds
        )
    ;
    
      too_old
    | .DBSnapshotIdentifier
    

    如果你把它放在一个文件 filter.jq 中并使用 -r 选项运行 jq,例如

    jq -M -r -f filter.jq input.json
    

    它将产生您要求的输出:

    alex-dbs-16opfr84gq4h9-snapshot-rtsmdbinstance-fr84gq4h9
    alex3-20170422-update 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-09-22
      • 2020-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多