Grep在Shell中的两个时间戳之间记录

时间:2015-12-25 10:57:22

标签: regex bash shell unix grep

我正在编写一个脚本,我需要在两个给定的时间戳之间准确地grep日志。我不想使用正则表达式,因为它不是完全证据。还有其他方法可以实现这个目标吗?

例如:时间范围04:15:00至05:15:00

日志格式:

170.37.144.10 - - [17/Dec/2015:04:00:00 -0500] "GET /abc/def/ghi/xyz.jsp HTTP/1.1" 200 337 3440 0000FqZTmTG2yuMTJeny7hPDOvG
170.37.144.10 - - [17/Dec/2015:05:10:09 -0500] "POST /abc/def/ghi/xyz.jsp HTTP/1.1" 200 27 21124 0000FqZTmTG2yuMTJ

2 个答案:

答案 0 :(得分:2)

如果您不想使用正则表达式或模式来匹配行,那么单独使用grep是不够的。

这是一个Bash +日期解决方案:

# start and stop may be parameters of your script ("$1" and "$2"),
# here they are hardcoded for convenience.
start="17/Dec/2015 04:15:00 -0500"
stop="17/Dec/2015 05:15:00 -0500"

get_tstamp() {
    # '17/Dec/2015:05:10:09 -0500' -> '17/Dec/2015 05:10:09 -0500'
    datetime="${1/:/ }"
    # '17/Dec/2015 05:10:09 -0500' -> '17 Dec 2015 05:10:09 -0500'
    datetime="${datetime//// }"

    # datetime to unix timestamp
    date -d "$datetime" '+%s'
}

start=$(get_tstamp "$start")
stop=$(get_tstamp "$stop")

while read -r line
do
    datetime="${line%%:*}" # remove ':170.37.144.10 ...'
    tstamp="$(get_tstamp "$datetime")"

    # $tstamp now contains a number like 1450347009;
    # check if it is in range $start..$stop
    [[ "$tstamp" -ge "$start" && "$tstamp" -le "$stop" ]] && echo "$line"
done

答案 1 :(得分:1)

这可能是您想要做的,使用GNU awk进行时间函数:

$ cat tst.awk
BEGIN { FS="[][ ]+"; beg=t2s(beg); end=t2s(end) }
{ cur = t2s($4) }
(cur >= beg) && (cur <= end)

function t2s(time,      t) {
    split(time,t,/[\/:]/)
    t[2]=(match("JanFebMarAprMayJunJulAugSepOctNovDec",t[2])+2)/3
    return mktime(t[3]" "t[2]" "t[1]" "t[4]+0" "t[5]+0" "t[6]+0)
}

$ awk -v beg="17/Dec/2015:04:15" -v end="17/Dec/2015:05:15" -f tst.awk file
access_log.aging.20151217040207:170.37.144.10 - - [17/Dec/2015:05:10:09 -0500] "POST /abc/def/ghi/xyz.jsp HTTP/1.1" 200 27 21124 0000FqZTmTG2yuMTJ

但如果没有更多的样本输入和预期的输出,就很难猜到。