如何按日期时间范围grep?

3 投票
5 回答
5012 浏览
提问于 2025-04-16 15:01

我有一个日志文件,内容大概是这样的:

2011-03-21 00:01 xxxx
2011-03-22 04:05 xxxx
....
2011-03-25 10:12 xxxx
....
2011-04-04 12:23 xxxx

我想写一个脚本,这个脚本需要两个参数,表示日期范围,比如:

grep-date-range.sh 2011-03-25 2011-04-02

它会找到所有在[2011-03-25, 2011-04-02]之间的日志。我知道在特定情况下可以用通配符,但我觉得这不是一个通用的方法。有没有人能给我一个解决方案?

补充: Python脚本也可以接受。

5 个回答

1

好的,我终于明白这个了。基本的思路是使用 sort -m 来合并给定的日期,然后用 sed 把那些已知的行提取出来(感谢“用户未知”的建议)。如果数据文件还没有排序,先对它进行排序。这里的假设是 YYYY-MM-DD 是一个固定的格式,否则这样做就不行了。

你可以通过使用 mktemp 来替代 /tmp/startstop,并且用更独特的字符串代替“START”和“END”,让这个过程更稳健。

/tmp/data 显然就是你的数据文件。

#!/bin/bash

START=$1
END=$2

echo $START START > /tmp/startstop
echo $END END >> /tmp/startstop

sort -m /tmp/data /tmp/startstop | sed -n '/START/,/END/p'
2
sed -n "/$1/,/$2/p" $3

调用它:

fromTo "2011-03-25" "2011-04-02" foo.log

sed

  • -n: 不输出任何内容
  • /from/,/to/: 要匹配的模式
  • p: 打印

文件中必须存在这些日期,如果你只在里面有2011-03-24和2011-03-26,这个方法就不管用了。它是字符串匹配,而不是日期匹配。你不需要加引号,但我碰巧有另一种日期格式,所以在我的测试中用了(比如“Mar 23”等)。

2

在这种情况下,写一个简单的Python脚本可能会更好。Python语言在处理日期方面的功能很强大,非常方便。

下面的脚本非常简单,如果再多花点功夫,它可以处理本地时间差、夏令时等等问题。

#! /usr/bin/python
import sys
from datetime import datetime
d_format = "%Y-%m-%d"

try:
    start = datetime.strptime(sys.argv[1], d_format)
    end = datetime.strptime(sys.argv[2], d_format) 
except (TypeError, IndexError):
    sys.stderr.write("Example: grep-date-range.py 2011-03-25 2011-04-02 \n")

for line in sys.stdin:
    try:
        date = datetime.strptime(line.split()[0], d_format)
        # suit the <=, <, comparisons bellow to your needs:
        if start <= date < end:
            sys.stdout.write(line)
    except (ValueError, IndexError):
        pass 

撰写回答