我有一个很大的文件文本(几乎 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
答案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)
您通过变量提供开始和结束时间starttime
,endtime
格式如下: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) 后未指定任何操作,因此默认操作是打印该范围内的行。