Awk以时间格式打印出最小和最高的数字

时间:2017-10-11 16:17:16

标签: bash awk awk-formatting

我对linux / bash shell比较陌生,而且我在从文本文件中的特定列打​​印两个值(最高和最低)时遇到了麻烦。文件格式如下:

Geoff        Audi           2:22:35.227
Bob          Mercedes       1:24:22.338
Derek        Jaguar         1:19:77.693
Dave         Ferrari        1:08:22.921

正如您所看到的,最后一列是时间,我尝试使用awk打印出列中的最高和最低时间。我真的很难过,我已经尝试过:

awk '{print sort -n <  $NF}' timings.txt 

然而,这似乎没有任何排序,我只收到了一个输出:

1
0
1
0
...

一遍又一遍地重复,它持续了很长时间,但是当你在第一次迭代之后得到这个点时,我并不想要它的大量线。

我想要的输出是:

Min: 1:08:22.921
Max: 2:22:35.227   

3 个答案:

答案 0 :(得分:3)

问题后说明:如果时间字段在同一位置始终具有相同的位数,例如 h:mm:ss.ss ,可以大大简化解决方案。也就是说,我们不需要将时间转换为秒来进行比较,我们可以进行简单的字符串/词典编纂比较:

$ awk 'NR==1 {m=M=$3} {$3<m&&m=$3; $3>M&&M=$3} END {printf("min: %s\nmax: %s",m,M)}' file
min: 1:08:22.921
max: 2:22:35.227

逻辑与下面的(上一个)脚本中的逻辑相同,只是使用更简单的基于字符串的比较来排序值(确定最小值/最大值)。我们可以这样做,因为我们知道所有时间都符合相同的格式,如果a < b(例如"1:22:33" < "1:23:00")我们知道a是&#34;更小&#34;比b。 (如果值没有一致地格式化,那么仅通过使用词典编纂比较,我们就无法对它们进行排序,例如"12:00:00" < "3:00:00"。)

因此,在第一个值读取(第一个记录,NR==1)时,我们将初始最小/最大值设置为读取的时间(在第3个字段中)。对于每个记录,我们测试当前值是否小于当前min,如果是,我们设置新的min。同样的最大值。我们使用短路代替if来缩短表达式($3<m && m=$3相当于if ($3<m) m=$3)。在END中,我们只是打印结果。

这是一般awk解决方案,接受每个记录的小时/分钟/秒的可变位数的时间字符串:

$ awk '{split($3,t,":"); s=t[3]+60*(t[2]+60*t[1]); if (s<min||NR==1) {min=s;min_t=$3}; if (s>max||NR==1) {max=s;max_t=$3}} END{print "min:",min_t; print "max:",max_t}' file
min: 1:22:35.227
max: 10:22:35.228

或者,以更易读的形式:

#!/usr/bin/awk -f
{
    split($3, t, ":")
    s = t[3] + 60 * (t[2] + 60 * t[1])
    if (s < min || NR == 1) {
        min = s
        min_t = $3
    }
    if (s > max || NR == 1) {
        max = s
        max_t = $3
    }
}

END {
    print "min:", min_t
    print "max:", max_t
}

对于每一行,我们将时间分量(小时,分钟,秒)从第三个字段转换为秒,以后我们可以简单地将其作为数字进行比较。在迭代时,我们跟踪当前的最小值和最大值,并在END中打印它们。 min和max的初始值取自第一行(NR==1)。

答案 1 :(得分:2)

鉴于你的陈述时间字段实际上是一个持续时间而小时部分总是一个数字,这就是你所需要的:

$ awk 'NR==1{min=max=$3} {min=(min<$3?min:$3); max=(max>$3?max:$3)} END{print "Min:", min ORS "Max:", max}' file
Min: 1:08:22.921
Max: 2:22:35.227

答案 2 :(得分:1)

您不希望在awk中运行sort(即使使用正确的语法)。

试试这个:

sed 1d timings.txt | sort -k3,3n | sed -n '1p; $p'

,其中

  • 第一个sed将删除标题
  • 按数字排序第3列
  • 第二个sed将打印第一行和最后一行