我有以下格式的日志文件:
20:15:35 start opsdfslkdfflkjsdlkfjlsdkfj
20:17:21 lkjlkj lklkjlkjlkjlkjlkjlkjlkjlkj
.
.
.
20:34:11 end kljsdklasjdlaksjdasdasd
20:36:20 start lksadjlaskjdalksdj
.
.
etc
解析此文件的结果是,我希望得到后续项start
和end
条目之间的时间差。为了保持一致性,应该在bash中完成(其他日志解析在bash中使用gnuplot进行绘制)。但是通过将文件重定向到while
循环然后使用例如awk
将时间戳转换为秒来读取文件,会使整个解析变得极其缓慢(可能是由于每行创建了一个新的子进程)。
while read line; do
if [[ $string == *"start"* ]]
then
start=$(echo $line | awk '{print $1}' | awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }')
echo $start
fi
done <log.txt
有什么想法可以在bash中有效地做到这一点吗?
它比纯awk
实例要慢,但是在本机bash中,仅使用shell内置函数:
while IFS=': ' read -r hr min sec content; do
if [[ $content = *"start"* ]]; then
start=$(( hr * 3600 + min * 60 + sec ))
echo "$start"
fi
done <log.txt
这也将以适当的David Korn ksh运行-快得多。(如果使用诸如mksh之类的ksh克隆而不是合法的文章,则结果(尤其是性能结果)将有所不同)。
另外,对于pure awk
,您可以完全避免while read
在bash中出现任何循环:
awk -F: '/start/ { print ($1 * 3600) + ($2 * 60) + $3 }' <log.txt
要以bash方式实现整个过程(识别开始/结束对并打印增量),可能看起来像这样:
while IFS=': ' read -r hr min sec sigil rest; do
case $sigil in
start) start_sec=$(( hr * 3600 + min * 60 + sec )); end_sec= ;;
end) end_sec=$(( hr * 3600 + min * 60 + sec ))
if [[ $start_sec ]]; then
echo "$start_sec->$end_sec -- $(( end_sec - start_sec )) elapsed"
start_sec=
fi
;;
esac
done <log.txt
...或者,对于awk的全部内容:
awk -F: '
/start/ { start=( ($1 * 3600) + ($2 * 60) + $3 ) }
/end/ { end=( ($1 * 3600) + ($2 * 60) + $3 );
if (start) {
print start " -> " end " -- " (end - start) " elapsed"
start=0
}
}
' <log.txt
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句