2017-10-11 34 views
3

我对linux/bash shell相当陌生,而且我真的无法从文本文件的特定列中打印两个值(最高和最低)。该文件的格式是这样的:
Awk在时间格式上打印出最小和最高的数字

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 
+0

您是否尝试过这样的事情?他们将最后一列分成3列(小时,分钟,秒)并将它们用于排序 https://stackoverflow.com/questions/22053402/awk-is-it-possible-to-read-a-timefield用于分拣 –

+0

只需补充一点,我意识到我尝试的输出是按顺序对它们进行排序,那只是我测试出来的结果是否可以确定最高和最低 - 而不是它是否会打印出于最高和最低,这仅仅是一个起点。最终目标是打印最高时间和最低时间。 –

+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"),我们知道ab“小”。 (如果值不一致的格式,然后通过单独使用逐一比较,我们不能命令他们,例如"12:00:00" < "3:00:00"。)

因此,在第一值读取(第一个记录,NR==1)中,我们设置初始分钟/读取时间的最大值(在第3个字段中)。对于每个记录,我们测试当前值是否小于当前最小值,如果是,则设置新的最小值。类似的最大。我们使用短路代替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 
} 

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

+1

你不需要做任何时间的数学计算,只需把整个时间看作一个单一的数字 – 123

+0

谢谢,这回答了我的问题,但更重要的是它帮助我了解每一步发生了什么。我对这种东西完全陌生,所以它有助于解决方案的解释。 –

+0

@ 123,不知道。谢谢,我会更新我的答案。 – randomir

1

你不想(即使有正确的语法)排序中的awk的运行。

尝试这种情况:

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

其中

  • 第一sed的将去除头
  • 排序在第3列数字
  • 第二sed的将打印的第一和最后一行
+0

嗨,谢谢你的回复!我已经使用了这一点并理解了每一步,但是我只得到了一个输出 - 然而我得到的输出确实是列表中最大的时间,但最小的时间似乎并没有显示出来?一个可能的原因,虽然我没有完全用这个东西先进的是,最大的时间是唯一一个冒号前2,所有其他人开始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 
相关问题