[英]Awk printing out smallest and highest number, in a time format
我是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
问题澄清 后 :如果时间字段总是具有在同一个地方一个相同的位数,例如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
比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
)。
鉴于您的陈述时间字段实际上是一个持续时间而小时组件始终是一个数字,这就是您所需要的:
$ 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
你不想在awk中运行sort(即使使用正确的语法)。
试试这个:
sed 1d timings.txt | sort -k3,3n | sed -n '1p; $p'
哪里
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.