Awk распечатывает наименьшее и наибольшее число в формате времени
Я довольно новичок в оболочке linux/bash, и у меня действительно возникают проблемы при печати двух значений (самое высокое и самое низкое) из определенного столбца в текстовом файле. Файл отформатирован так:
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 ответа
После уточнения вопроса: если поле времени всегда имеет одинаковое количество цифр в одном и том же месте, например 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
), мы устанавливаем начальное значение min/ max для считывания времени (в 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
}
Для каждой строки мы преобразуем временные компоненты (часы, минуты, секунды) из третьего поля в секунды, которые позже мы можем просто сравнить как числа. В процессе итерации мы отслеживаем текущие значения min val и max val, печатая их в 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 (даже с правильным синтаксисом).
Попробуй это:
sed 1d timings.txt | sort -k3,3n | sed -n '1p; $p'
где
- первый сед удалит заголовок
- отсортировать по 3-му столбцу численно
- второй седь напечатает первую и последнюю строку