在澄清问题之后:如果时间字段始终在相同位置具有相同数量的数字,例如
h:mm:ss.ss
,则解决方案可以大大简化。换句话说,我们不再需要将时间转换为秒来进行比较,而是可以进行简单的字符串/字典比较。
$ awk 'NR==1 {m=M=$3} {$3<m&&m=$3
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
),我们将初始的最小/最大值设置为读取的时间(在第三个字段中)。对于每条记录,我们测试当前值是否小于当前最小值,如果是,则设置新的最小值。类似地,对于最大值也是如此。我们使用短路运算而不是
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
中打印它们。最小和最大值的初始值来自第一行(NR==1
)。