我,新手,已经搜索了这个论坛,并尝试了几个awk,seds和greps。
我正在尝试搜索日志文件以输出日期和时间内的所有日志。
不幸的是,我正在搜索的日志都有不同的日期格式。
我确实让这个工作:
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="Aug 23, 2018 17:00:00" , TO="Aug 23, 2018 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 一起工作——再次,我认为这可能是一个空间问题? 不知道如何解决....
这是一个难题。grep
和sed
都没有日期的概念,甚至 GNUawk
对日期和时间的支持也有限。
如果您使用合理的日期格式,即可用于字符串比较的日期格式,例如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
前两个应该有效,但前提是文件确实包含两个时间戳,因为您只检查是否存在某些任意字符串。第三个也应该有效,前提是所有记录都以时间戳开头。
这可能是您要查找的内容(对输入文件的外观做出一些假设(:
$ 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。
当尝试获取出现在两个日期之间的一组日志条目时,切勿使用sed
来检查这一点。是的,sed 确实有一个很酷且非常有用的功能来检查地址范围(顺便说一句,awk 顺便说一句也是如此(。
sed -n `/date1/,/date2/p` file
不会总是有效。这意味着只有当date1
和date2
实际在文件中时,它才会起作用。如果缺少其中一个,这将失败。
具有两个地址的编辑命令应选择从与第一个地址匹配的第一个模式空间到与第二个地址匹配的下一个模式空间的包含范围。
[address[,address]]
最重要的是,在比较日期时,除非您使用合理的格式,否则永远不应该使用字符串比较。一些理智的格式是YYYY-MM-DD
,YYYY-MM-DD hh:mm:ss
,...一些不好的格式是"Aug 1 2018",因为它在"Jan 1 2018"之前,"99-01-31"在"01-01-31"之后,或者"2018-2-1"在"2018-11-1"之后
因此,如果可以的话,请尝试将您获得的日期转换为合理的格式。最明智的格式是计算一个纪元的日期差。Unix有各种工具可以计算自1970-01-01 00:00:00 UTC的UNIX纪元以来的秒数。这才是你真正追求的。
正如您提到的,您的日志文件具有各种日期格式,这并不容易。尽管 gnu awk 有各种时间函数,但它们需要你事先知道格式。
由于我们不知道您的日志文件中存在哪些格式,因此我们将使用 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