JSON JQ filter by date later than bash

eivgtgni  于 2023-10-21  发布在  其他
关注(0)|答案(3)|浏览(115)

我在text.json文件中有一个包含这种格式数据的json

[
  {
    "name": "page/page1.html",
    "properties": {
      "lastModified": "2021-08-10T18:00:45+00:00",
    }
  },
  {
    "name": "page/page2.html",
    "properties": {
      "lastModified": "2021-08-10T19:24:23+00:00",
    }
  },
  {
    "name": "page/page3.html",
    "properties": {
      "lastModified": "2021-08-10T20:36:21+00:00",
    }
  }
]

我想做一个列表,列出30分钟前最后一次修改的所有文件名。这是我目前的查询,以获得一个文件名列表作为变量,我可以稍后使用。

file_names=`cat text.json | jq -r .[].name`

我如何使用jq根据属性中的时间戳过滤lastModified超过30分钟,这样我就只得到相关的文件名?

p4tfgftt

p4tfgftt1#

我通常会在native bash中计算目标日期。

#!/usr/bin/env bash
# make sure we have bash new enough for printf %(...)T time-formatting
# this makes our script work even without GNU date
case $BASH_VERSION in
  ''|[123].*|4.[012].*) echo "ERROR: bash 4.3+ required" >&2; exit 1;;
esac

export TZ=UTC # force all timestamps to be in UTC (+00:00 / Z)

# faster, bash-builtin now=$(date +%s)
printf -v now '%(%s)T' -1

# faster, bash-builtin start_date_iso8601=$(date +%s -d '30 minutes ago')
start_date_epoch=$((now - 60*30))
printf -v start_date_iso8601 '%(%Y-%m-%dT%H:%M:%S+00:00)T' "$start_date_epoch"

# read our resulting names into an array (not a string)
# jq -j suppresses newlines so we can use NUL delimiters
while IFS= read -r -d '' name; do
  names+=( "$name" )
done < <(
  jq -j --arg start_date "$start_date_iso8601" '
    .[] |
    select(.properties.lastModified < $start_date) |
    (.name, "\u0000")
  ' <text.json
)

# print the content of the array we just read the names into
printf 'Matching name: %q\n' "${names[@]}"
pw136qt2

pw136qt22#

这似乎工作

date=`date +%Y-%m-%d'T'%H:%M'Z' -d "15 min ago"`

file_names=`jq -r --arg date "$date" '.[] | select(.properties.lastModified < $date) | .name' < text.json`
55ooxyrt

55ooxyrt3#

jq执行所有日期计算:
使用bash 4及更高版本的mapfile

mapfile -d '' last_modified < <(
  jq --join-output '(now - 1800) as $date | .[] | select((.properties.lastModified | .[:18] + "Z" | fromdate) < $date) | .name + "\u0000"' input_file.json
)

# For debug purpose
declare -p last_modified

如果没有mapfile,记录将使用ASCII RS控制字符而不是null字节进行分隔:

IFS=$'\36' read -ra last_modified < <(jq -j '(now - 1800) as $date | .[] | select((.properties.lastModified | .[:18] + "Z" | fromdate) < $date) | .name + "\u001e"' input_file.json)

以下是带有注解的独立jq脚本:

#!/usr/bin/env -S jq -jf

# Store current timestamp minus 30 minutes (1800 seconds) as $date
(now - 1800) as $date |
 .[] |
#
select(
  (
    # Strip the numerical timezone offset out from the timestamp
    # and replace it with the Z for UTC iso8601
    # to make it an iso8601 date string that jq understands
    .properties.lastModified | .[:18] + "Z" | fromdate
  ) < $date
) |
.name + "\u0000"

相关问题