我有一个大小接近3 3GB的大型日志文件。
我的任务是根据记录的次数生成一些报告。
我需要找出StringA,StringB,StringC分别被调用的次数。
我现在要做的是:
grep "StringA" server.log | wc -l
grep "StringB" server.log | wc -l
grep "StringC" server.log | wc -l这是一个很长的过程,我的脚本需要将近10分钟才能完成。我想知道的是,这是否可以优化?是否可以运行一个grep命令并找出分别调用StringA、StringB和StringC的次数?
发布于 2016-01-31 14:09:26
您可以使用grep -c而不是wc -l:
grep -c "StringA" server.loggrep无法报告单个字符串的计数。您可以使用awk:
out=$(awk '/StringA/{a++;} /StringB/{b++;} /StringC/{c++;} END{print a, b, c}' server.log)然后,您可以使用一个简单的bash数组来提取每个计数:
arr=($out)
echo "StringA="${arr[0]}
echo "StringA="${arr[1]}
echo "StringA="${arr[2]}这种(没有wc的grep)肯定会更快,可能awk解决方案也会更快。但我什么都没测过。
发布于 2016-01-31 13:21:22
当然,这种方法可以优化,因为grep不执行任何文本索引。我会使用文本索引引擎,比如this review或这个stackexchange QA中的一个。此外,您还可以考虑使用systemd中的journald,它以结构化和索引格式存储日志,因此查找更加有效。
发布于 2016-01-31 13:41:53
那么多的greps这么少的时间...:-)
根据David Lyness的说法,在大文件搜索中,直接grep搜索的速度大约是awk的7倍。
如果是这种情况,可以通过将grep更改为fgrep来优化当前方法,但前提是要搜索的模式不是正则表达式。fgrep针对固定模式进行了优化。
如果与原始日志文件条目相比,实例数量相对较少,则使用grep的egrep版本创建一个填充了所有三个实例的临时文件可能会有所改进:
egrep "StringA|StringB|StringC" server.log > tmp.log
grep "StringA" tmp.log | wc -c
grep "StringB" tmp.log | wc -c
grep "StringC" tmp.log | wc -cgrep的egrep变体允许在两个或多个单独的搜索字符串之间使用| (竖线/竖线)字符,以便您可以在语句中查找多个字符串。您可以使用grep -E来做同样的事情。
完整的文档在man grep页面中,以及关于man 7 re_format命令使用的扩展正则表达式的信息。
https://stackoverflow.com/questions/35109478
复制相似问题