如何在大型文本文件中使用 grep/sed 获取日期范围内的文本?

如何在大型文本文件中使用 grep/sed 获取日期范围内的文本?

我有一个很大的文件文本(几乎 3GB)——它是一个日志文件。我想从这个文件中获取与日期范围(从 7 月 13 日到 7 月 19 日)相对应的文本行。我的日志格式是:

2016-07-12 < ?xml version>
2016-07-13 < ?xml version>
2016-07-18 < ?xml version>
2016-07-18 < ?xml version>
2016-07-19 < ?xml version>
2016-07-20 < ?xml version>
sample text sample text
sample text sample text
sample text sample text
2016-07-20 < ?xml version>
sample text sample text
2016-07-20 < ?xml version>

所以grep/之后sed应该输出如下内容:

2016-07-13 < ?xml version>
2016-07-18 < ?xml version>
2016-07-18 < ?xml version>
2016-07-19 < ?xml version>

我如何获得它?

答案1

如果grep你知道你想要的行数,你可以使用上下文选项-A来打印模式后的行

grep -A 3 2016-07-13 file

这将为您提供 2013-07-13 行以及接下来的 3 行

sed可以用日期来划定这样的界限

sed -n '/2016-07-13/,/2016-07-19/p' file

这将打印从第一行 2016-07-13 到第一行 2016-07-19 的所有行。但这假设您只有一行 2016-07-19(它不会打印下一行)。如果有多行,请使用下一个日期,并使用d从中删除输出

sed -n '/2016-07-13/,/2016-07-20/{/2016-07-20/d; p}' file

答案2

这个简单的 grep 单行命令就足够了:

grep -E ^2016-07-1[3-9] filename

这里运行良好,不需要 sed :)

参考:

答案3

所有其他当前答案都依赖于日志文件条目按时间顺序排序的事实或日期范围可以轻松与正则表达式匹配的事实。如果您想要更通用的解决方案,我们需要进行更多编程。

我介绍这个 GNU AWK 脚本:

#!/usr/bin/gawk -f
BEGIN {
    starttime = mktime(starttime)
    endtime = mktime(endtime)
}

func in_range(n, start, end) {
    return start <= n && n < end
}

match($0, /^([0-9]{4})-([0-9]{2})-([0-9]{2})\s/, m) &&
    in_range(mktime(m[1] " " m[2] " " m[3] " 00 00 00"), starttime, endtime)

您通过变量提供开始和结束时间starttimeendtime格式如下:mktime理解(YYYY MM DD hh dd ss)。因此,您可以awk像这样运行命令,假设上述 Awk 脚本位于filter-log-dates.awk当前工作目录中的可执行文件中,并且日志文件为mylog.txt

./filter-log-dates.awk -v starttime='2016 07 13 00 00 00' -v endtime='2016 07 20 00 00 00' mylog.txt

请注意结束时间是独家的即有效的日志记录必须有时间戳结束时间。

如果您的时间戳格式不同,您可以调整传递给match函数的正则表达式以适应它。

答案4

您可以分步进行。找到与您的起始模式匹配的第一行的行号。找到与您的结束模式匹配的最后一行的行号。然后提取这两行之间的测试。这可以按如下方式完成。

grep -n 2016-07-13 bigtextfile | head -1
grep -n 2016-07-19 bigtestfile | tail -1
# Say the first number is 1234 and the second 5678, then use...
awk 'NR>=1234 && NR<=5678' bigtestfile > rangeoftext

这可以在一个命令中完成awk,但步骤可能会使其更容易遵循。在 awk 中,NR 变量是当前行号,并且由于模式 (NR>=1234 && NR<=5678) 后未指定任何操作,因此默认操作是打印该范围内的行。

相关内容