我需要 grep 最后 5 分钟的日志。日志文件:
18-06-17 06:00:09 ID-5
18-06-17 06:00:11 ID-78
20-06-17 09:34:51 ID-Hello
21-06-17 09:20:49 link is down
22-06-17 06:00:11 ID-674
22-06-17 06:40:51 ID-2
22-06-17 06:40:55 ID-7
22-06-17 06:40:16 ID-3
22-06-17 06:42:20 ID-2
date +"%d-%m-%y %k:%M:%S"
22-06-17 06:43:40
我试过:
awk -v date=$(date -d "30 minutes ago" +"%d-%m-%y %k:%M:%S") '$1" "$2 >= date { print $0 }' log
但有错误:
awk: cmd. line:1: 06:43:40
awk: cmd. line-1- ^ syntax error
你能帮我解决这个问题吗?
答案1
如果您的日期/时间结构为 yy-mm-dd hh:mm:ss 而不是 day first,那么您可以执行字符串比较以过滤给定日期之后的行。要重新格式化数据,请使用
sed 's/\(..\)-\(..\)-\(..\)\(.*\)/\3-\2-\1\4/' log > log.reformatted
然后,您可以使用 awk 将给定日期和时间之后的行连接在一起来打印它们,例如
awk '$1 " " $2 >= "17-06-22 06:40:00"' log.reformatted
您使用 date 来获取 30 分钟前的时间是好的 - 只需将其更改为年月日格式。您不需要 print $0 操作,因为如果没有指定任何操作,则暗示该操作。
请注意,我假设“grepping”的意思是使用 Unix 工具来过滤可用数据的所需子集。
原始错误可能是由于日期和时间之间的空格导致的,因此参数-v
仅接收日期,而时间则显示为单独的参数,这会使 awk 感到困惑。要解决这个问题,请使用格式%H
而不是%k
(因为您的日志格式无论如何都是两位数的小时),并删除日期和小时之间的空格(作为问题的简单解决方案)。然后整个解决方案变成:
sed 's/\(..\)-\(..\)-\(..\)\(.*\)/\3-\2-\1\4/' log |
awk -v date=$(date -d "30 minutes ago" +"%y-%m-%d%H:%M:%S") '$1$2 >= date'
答案2
一体化awk
命令,兼容gawk
、mawk
和POSIX awk 规范:
$ awk -F '[- ]' -v target="$(date -d '30 minutes ago' +'%y-%m-%d %T')" '
{ time = sprintf("%02d-%02d-%02d %s", $3, $2, $1, $4) }
time >= target
' log
首先,我awk
以一种接受连字符和空格作为分隔符的方式进行调用,这样可以更简单地解析日期。命令awk
行还调用以 yy-mm-dd HH:MM:SS 格式date
定义一个time
变量(从最高有效单位到最低有效单位,以便对其进行排序)。
其中的第一行awk
使用相同的时间格式来设置time
日志每一行的变量。然后,第二行以文本方式将日志行的时间与目标时间进行比较。 awk
的默认操作是打印,因此它会打印该行。
相对于问题的“22-06-17 06:43:40”,使用“30 分钟前”:
$ awk -F '[- ]' -v target="$(date -d '2017-06-22 06:13:40' +'%y-%m-%d %T')" '
{ time = sprintf("%02d-%02d-%02d %s", $3, $2, $1, $4) }
time >= target
' log
22-06-17 06:40:51 ID-2
22-06-17 06:40:55 ID-7
22-06-17 06:40:16 ID-3
22-06-17 06:42:20 ID-2