我有以下 jq 命令的输出,我想比较所有日期和时间并告诉哪个是最新的
Mon Feb 20 09:22:25 2023
Mon Feb 20 17:42:13 2023
Thu Mar 2 05:55:07 2023
Tue Feb 28 16:02:40 2023
请指导我如何做到这一点,我似乎有多个比较两个日期的答案,不确定如何比较日期和时间,还要比较我是否需要将上述时间戳转换为特定格式,
请指导
问候,武士
答案1
假设您有一些如下所示的 JSON 文档:
[
{ "datestring": "Mon Feb 20 09:22:25 2023" },
{ "datestring": "Mon Feb 20 17:42:13 2023" },
{ "datestring": "Thu Mar 2 05:55:07 2023" },
{ "datestring": "Tue Feb 28 16:02:40 2023" }
]
(您可以使用问题中的数据创建此数据jq -Rn '[inputs] | map({datestring: .})'
,但我假设您已经在某个 JSON 文档中拥有此数据。)
...然后您可以使用和jq
将这些日期字符串转换为 Unix 时间戳(整数),然后使用这些时间戳作为排序键对原始字符串进行排序。strptime()
mktime
jq 'sort_by(.datestring|strptime("%a %b %e %H:%M:%S %Y")|mktime)' file
这将计算示例文档中顶级数组中每个条目的 Unix 时间戳。它通过使用给定的特定格式字符串解析给定的日期字符串(请参阅系统上的strptime()
手册了解此格式字符串的含义)并将生成的时间表示形式转换为带有.然后使用该 Unix 时间戳按升序对条目进行排序。strptime
mktime
sort_by()
鉴于上面的示例文档,这将产生与以下内容等效的内容:
[
{ "datestring": "Mon Feb 20 09:22:25 2023" },
{ "datestring": "Mon Feb 20 17:42:13 2023" },
{ "datestring": "Tue Feb 28 16:02:40 2023" },
{ "datestring": "Thu Mar 2 05:55:07 2023" }
]
一种稍微更有效的方法是预先计算 Unix 时间戳,使用它们进行排序,然后再次删除它们(一种施瓦茨变换):
jq 'map(.ts = (.datestring|strptime("%a %b %e %H:%M:%S %Y")|mktime)) | sort_by(.ts) | map(del(.ts))' file
答案2
您可以使用date
命令将这些日期转换为unix时间戳并对它们进行排序,然后您可以将它们转换回您想要的任何格式。
例如,将日期转换为时间戳,然后再转换回来:
date -d "Mon Feb 20 09:22:25 2023" +%s
1676884945
date -d "@1676884945" +%c
Mon Feb 20 09:22:25 2023
-d
表示显示字符串中表示的日期/时间,如果您使用unix时间,则需要放在@
时间之前+%s
表示以 UNIX 纪元时间显示日期+%c
表示以区域设置时间格式显示日期
然后,您可以将它们放入一些循环中,并将时间转换为 unix 纪元,轻松排序,并将排序后的时间转换回您想要的任何时间格式。
如果 datefile 中有日期,这会将它们转换为 unix 时间戳并对其进行排序。
while IFS= read -r line; do date -d "$line" +%s; done < datefile | sort -n
然后您可以将这些排序后的格式转换回您想要的任何格式
for i in $(while IFS= read -r line; do date -d "$line" +%s; done < datefile | sort -n); do date -d "@$i" +%c; done
对于你给出的例子,你会得到这样的东西
for i in $(while IFS= read -r line; do date -d "$line" +%s; done < datefile | sort -n); do date -d "@$i" +%c; done
Mon Feb 20 09:22:25 2023
Mon Feb 20 17:42:13 2023
Tue Feb 28 16:02:40 2023
Thu Mar 2 05:55:07 2023
请注意,当您使用 %c 时,您将获得符合您的区域设置的格式的输出,因此不需要您想要的格式。
如果您想确保从示例中获取格式,则需要使用+'%a %b %d %T %Y'
for i in $(while IFS= read -r line; do date -d "$line" +%s; done < datefile | sort -n); do date -d "@$i" +'%a %b %d %T %Y'; done
Mon Feb 20 09:22:25 2023
Mon Feb 20 17:42:13 2023
Tue Feb 28 16:02:40 2023
Thu Mar 02 05:55:07 2023
%a
缩写的三个字母日%b
缩写的三个字母月份%d
一个月中的某一天%T
带前导零的时间%Y
年
20230220092225
您还可以像格式一样转换为年、月、日、时间等所有数字,不带空格'%Y%m%dH%M%S'
,并使用该格式对日期进行排序或比较
date -d "Mon Feb 20 09:22:25 2023" +'%Y%m%d%H%M%S'
20230220092225
答案3
使用 GNUsort
或兼容版本,您可以使用以下命令按时间顺序对输入进行排序:
LC_ALL=C sort -b -k5,5rn -k2,2rM -k3,3rn -k4,4r
这里r
从最新到最旧的顺序排列,因此您可以通过管道head -n1
获取最新的。非标准部分是M
第二个排序键的标志,用于根据月份名称或缩写进行排序(此处用于LC_ALL=C
强制使用英文)。
注意jq
有时间解析和格式化功能,所以您应该能够直接从产生输出的调用jq
中对日期数组进行排序jq
首先。