awk从文件中的每一行和以下行打印字段

时间:2014-12-12 20:43:08

标签: awk sed ksh

我有一个文件,其中包含每封邮件的开始和结束时间:

msgid=1 11:34:12.410 11:34:12.464
msgid=2 11:34:12.465 11:34:12.563
msgid=3 11:34:12.563 11:34:12.577
msgid=4 11:34:12.849 11:34:12.850
msgid=5 11:34:12.950 11:34:12.951

我需要处理从一条消息结束到下一条消息开头的已用时间。

这是我能想到的最好的一行(我可以从那里获取)但是必须有一个更有效的方法使用awk和/或sed而不是while循环。文件中有20K行,所以这很慢。

var=`cat <file>| wc -l`
i=1
while [[ "$i" -le "$var" ]]; do
  awk 'NR=="'$i'" {print $1, $3}' <file>
  awk 'NR=="'$(($i + 1))'" {print $1, $2}' <file>
  i=$(($i + 1));
done

我用awk尝试过的方法总是推进记录并最终跳过一个,所以我会得到:

msgid=1 11:34:12.464 msgid=2 11:34:12.465
msgid=3 11:34:12.577 msgid=4 11:34:12.849
msgid=5 11:34:12.950 <..>

请注意,它缺少比较msgid 2和3等。

有什么想法吗?

使用输出格式更新我希望看到:

msgid=1 11:34:12.464 msgid=2 11:34:12.465
msgid=2 11:34:12.563 msgid=3 11:34:12.563
msgid=3 11:34:12.577 msgid=4 11:34:12.849
msgid=4 11:34:12.850 msgid=5 11:34:12.950

谢谢, 安迪

1 个答案:

答案 0 :(得分:3)

每次编写shell循环只是为了操作文本,你都有错误的方法。此外,永远不要让awk脚本中的shell变量扩展,就像你现在所做的那样,用双引号括起你的awk脚本。请参阅http://cfajohnson.com/shell/cus-faq-2.html#Q24

你展示了你不希望输出的东西,但不是你想要的东西,所以这是一个猜测:

$ cat tst.awk
end { print $1, ms($2) - end }
{ end = ms($3) }
function ms(t,   a) {
    split(t,a,/[:.]/)
    return (a[1]*60*60 + a[2]*60 + a[3]) * 1000 + a[4]
}

$ awk -f tst.awk file
msgid=2 1
msgid=3 0
msgid=4 272
msgid=5 100

你也不知道时间是否可以转换到第二天,或者DST是否是一个因素,等等,如果是这样,如果输入文件中没有日期,如何处理。