pik*_*wyn 1 bash performance awk parsing
我有以下格式的日志文件:
20:15:35 start opsdfslkdfflkjsdlkfjlsdkfj
20:17:21 lkjlkj lklkjlkjlkjlkjlkjlkjlkjlkj
.
.
.
20:34:11 end kljsdklasjdlaksjdasdasd
20:36:20 start lksadjlaskjdalksdj
.
.
etc
Run Code Online (Sandbox Code Playgroud)
在解析此文件的结果中,我希望在后续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
Run Code Online (Sandbox Code Playgroud)
有什么想法如何在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
Run Code Online (Sandbox Code Playgroud)
这也将在适当的David Korn ksh中运行得更快.(如果使用ksh克隆,例如mksh而不是合法文章,结果,特别是性能结果会有所不同).
或者,对于纯粹的awk,你可以避免while read在bash中有任何循环:
awk -F: '/start/ { print ($1 * 3600) + ($2 * 60) + $3 }' <log.txt
Run Code Online (Sandbox Code Playgroud)
在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
Run Code Online (Sandbox Code Playgroud)
...或者,对于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
Run Code Online (Sandbox Code Playgroud)