bash有效的文件解析

企鹅

我有以下格式的日志文件:

20:15:35 start opsdfslkdfflkjsdlkfjlsdkfj
20:17:21 lkjlkj lklkjlkjlkjlkjlkjlkjlkjlkj
.
.
.
20:34:11 end kljsdklasjdlaksjdasdasd
20:36:20 start lksadjlaskjdalksdj
.
.
etc

解析此文件的结果是,我希望得到后续startend条目之间的时间差为了保持一致性,应该在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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章