在日期/时间范围内搜索日志

时间:2018-08-23 21:46:18

标签: awk sed grep

我,新手,曾经在这个论坛上搜索过很多东西,并且尝试过几次awk,sed和grep。

我正在尝试搜索日志文件以输出日期和时间内的所有日志。

很遗憾,我正在搜索的日志都具有不同的日期格式

完成了,让它开始工作:

awk '$0 >= "2018-08-23.11:00:00" && $0 <= "2018-08-23.14:00:00"' catalina.out

针对该特定日期格式。

不能使用这些日期格式,也许是间距问题?

2018-08-23 11:00:00或2018年8月23日11:00:00

一些我尝试过的例子:

sed -n '/2018-08-23 16:00/,/2018-08-23 18:00/p' testfile.txt
sed -n '/Feb 23 13:55/,/Feb 23 14:00/p' testfile.txt
awk '$0 >= "2018-08-23 17:00:00" && $0 <= "2018-08-23 19:00:00"' testfile.txt

我也尝试设置变量:  FROM =“ 2018年8月23日17:00:00”,TO =“ 2018年8月23日19:00:00”

awk '$0 >= "$FROM" && $0 <= "$TO"' testfile.txt

有人可以帮我吗?

更新:我已将其用于2018-08-23 11:00:00格式

grep -n '2018-08-23 11:[0-9][0-9]' testfile.txt | head -1
grep -n '2018-08-23 12:[0-9][0-9]' testfile.txt | tail -1
awk 'NR>=2 && NR<=4' testfile.txt > rangeoftext

但是我无法使其与2018年8月23日11:00:00一起使用-再次,我认为这可能是空间问题?不确定如何解决。...

3 个答案:

答案 0 :(得分:1)

这是一个难题。 grepsed没有日期的概念,甚至GNU awk也仅对日期和时间提供了有限的支持。

如果您使用合理的日期格式,即可以在字符串比较中使用的日期格式,例如2018-08-15 17:00:00,该问题将变得更加易于解决。无论字符串是否包含空格,这都应该起作用。但是,请注意在空格上会自动拆分的工具,例如shell和awk

现在,以您的示例为例:

sed -n '/2018-08-23 16:00/,/2018-08-23 18:00/p' testfile.txt
sed -n '/Feb 23 13:55/,/Feb 23 14:00/p' testfile.txt
awk '$0 >= "2018-08-23 17:00:00" && $0 <= "2018-08-23 19:00:00"' testfile.txt

前两个应该起作用,但是仅当文件确实包含两个时间戳时才起作用,因为您仅在检查某些任意字符串的存在。如果所有记录均以时间戳开头,则第三种方法也应起作用。

答案 1 :(得分:1)

这可能就是您要寻找的内容(对输入文件的外观进行一些假设):

$ cat file
Aug 22, 2018 11:00:00 bad
2018-08-23 11:00:00 good
Aug 23, 2018 11:00:00 good
2018-08-24 11:00:00 bad

$ cat tst.awk
BEGIN {
    min = raw2dt(min)
    max = raw2dt(max)
}
{ cur = raw2dt($0) }
(cur >= min) && (cur <= max)

function raw2dt(raw,    tmp, mthNr, dt, fmt) {
    fmt = "%04d%02d%02d%02d%02d%02d"
    if ( match(raw,/[0-9]{4}(-[0-9]{2}){2}( [0-9:]+)?/) ) {
        split(substr(raw,RSTART,RLENGTH),tmp,/[^[:alnum:]]+/)
        dt = sprintf(fmt, tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6])
    }
    else if ( match(raw,/[[:alpha:]]{3} [0-9]{2}, [0-9]{4}( [0-9:]+)?/) ) {
        split(substr(raw,RSTART,RLENGTH),tmp,/[^[:alnum:]]+/)
        mthNr = (index("JanFebMarAprMayJunJulAugSepOctNovDec",tmp[1])+2)/3
        dt = sprintf(fmt, tmp[3], mthNr, tmp[2], tmp[4], tmp[5], tmp[6])
    }
    return dt
}

$ awk -v min='Aug 23, 2018 11:00' -v max='2018-08-23 11:00' -f tst.awk file
2018-08-23 11:00:00 good
Aug 23, 2018 11:00:00 good

以上内容可在任何UNIX盒的任何shell中使用任何POSIX awk进行工作。

答案 2 :(得分:0)

当尝试获取出现在两个日期之间的一组日志条目时,切勿使用sed进行检查。是的,sed确实具有很酷且非常有用的功能来检查地址范围(awk btw也是如此)。

sed -n `/date1/,/date2/p` file

并非总是有效。这意味着只有在文件中实际有date1date2时它才起作用。如果其中之一丢失,将失败。

  

具有两个地址的编辑命令应从与第一个地址匹配的第一个模式空间到与第二个地址匹配的下一个模式空间选择包含范围。

[address[,address]]

最重要的是,比较日期时,除非使用理智的格式,否则切勿使用字符串比较。某些理智的格式是YYYY-MM-DDYYYY-MM-DD hh:mm:ss,...一些不好的格式是“ 2018年8月1日”,它出现在“ 2018年1月1日”之前,而“ 99-01-31”是在“ 01- 01-31”或“ 2018-2-1”之后是“ 2018-11-1”

因此,如果可以,请尝试将获取的日期转换为合理的格式。最合理的格式是计算一个日期的日期差。 Unix有各种工具可以计算自1970年1月1日00:00:00 UTC的UNIX EPOCH起的秒数。这就是您真正想要的。

正如您提到的,您的日志文件具有各种日期格式,但这并不容易。即使gnu awk具有各种Time Functions,它们也要求您事先知道格式。

由于我们不知道您的日志文件中存在哪些格式,因此我们将使用unix函数date,该函数具有非常精巧的解释器,它知道许多格式。

此外,我将假设您可以在awk中唯一标识日期,并以某种方式将日期存储在名为date的字符串中。也许在日期之后总是出现一个特殊字符,您可以执行以下操作:

示例输入文件:

2018-08-23 16:00 | some entry
Aug 23 2018 16:01:01 | some other entry

因此,在这种情况下,我们可以说:

awk -F| -v t1=$(date -d "START_DATE" "+%s") \
        -v t2=$(date -d "END_DATE" "+%s")   \
        '{date=$1}
         {cmd="date -d \""$1"\" +%s"; cmd | getline epoch; close cmd}
         (t1 <= epoch && epoch <= t2)' testfile