我让这个项目来分析我的日志,我需要找到发生超过三次的任何连续错误并列出日志名称。由于我的日志很大,我写了下面的脚本:
for i in `ls`
do
count=`uniq -c $i | grep 'FATAL ERROR' |sed 's/^ *//g'| sed 's/ /,/g' | awk -F',' '{if($1 >1) {print $1}}'`
if [[ $count -ge 2 ]]
then
echo $i
fi
done
如果您只需要知道所有文件中出现的次数,则此方法有效
grep -o -c Source * | awk -F: '{if ($2 > 2){print $1}}'
我的脚本的更好版本是什么?如果日志真的很大,我的代码就会变慢怎么办?
答案1
管道通常应保持较短,并且为获取值所做的大部分操作count
都可以在单个程序中完成awk
,包括循环和if
语句。
awk 'FNR == 1 || !/FATAL ERROR/ { count = 0 }
/FATAL ERROR/ { ++count }
count == 2 { print FILENAME }' ./*
awk
这将在当前目录中的所有非隐藏文件上运行单个程序。
count
如果我们位于新文件的第一行,程序会将其变量重置为零或者如果当前行与模式不匹配FATAL ERROR
。
如果该行与模式匹配FATAL ERROR
,则count
变量会递增。
如果count
变量的值达到 2,则打印当前文件的名称。
每次找到与模式匹配的两个连续行时,代码都会打印文件名,即使这种情况在同一文件中发生多次。如果不需要,您可以稍微扩展代码:
awk 'FNR == 1 { count = 0; do_print = 1 }
!/FATAL ERROR/ { count = 0 }
/FATAL ERROR/ { ++count }
count == 2 && do_print { print FILENAME; do_print = 0 }' ./*
或使用 GNU awk
(用于nextfile
跳到下一个文件):
awk 'FNR == 1 || !/FATAL ERROR/ { count = 0 }
/FATAL ERROR/ { ++count }
count == 2 && do_print { print FILENAME; nextfile }' ./*
与您的 shell 循环相关: