В статье «Теория и практика построения рабочей процедуры сортировки» Дж. П. Линдерман показывает, что лучший способ получить хорошую производительность от системной команды sort
(которая является «программой сортировки», над которой он работал) со сложными ключами заключалась в создании команд для генерации ключей, упрощающих сравнение. В примере команда сортировки со сложным ключом была такой:
sort -t' ' -k 9,9.2 -k3 -k17
В альтернативном механизме использовался генератор ключей, чтобы упростить сортировку:
keygen | sort | keystrip
и генератор ключей был:
awk -F' ' '{printf "%s:%s:%s:%s\n", substr($9, 1, 2), $3, $17, $0}'
и съемник ключей был:
awk -F':' {printf "%s\n", $4}'
Для тестовых данных, с которыми работал Линдеман, истекшее время сократилось примерно с 2100 секунд для сложной команды сортировки до примерно 600 секунд для комбинации awk | sort | awk
.
Приняв эту идею здесь, я бы использовал сценарий Perl для единообразного представления разрозненных значений времени в формате, с которым sort
может справиться тривиально.
В этом случае у вас, похоже, есть несколько форматов времени, о которых нужно беспокоиться:
cpu time 9.05 seconds
real time 8:02.07
cpu time 2:25.23
real time 1:39:44.15
Непонятно, нужно ли сохранять контекст сортируемых строк, но мне кажется, что я бы привел времена к каноническому виду. Нужно ли разрешать 3-значные часы реального времени? Если время переходит на 20,05 секунды, остается ли суффикс? Если время доходит до 80,05 секунды, печатается ли оно как 1:20,05? Я предполагаю, что да...
#!/usr/bin/env perl
use strict;
use warnings;
while (<>)
{
if ($_ =~ m/ (?:cpu|real)\stime\s
(?:
(?:(\d+):)? # Hours
(\d\d?): # Minutes
)?
(\d\d?(?:\.\d+)) # Seconds
/msx)
{
my($hh, $mm, $ss) = ($1, $2, $3);
$hh //= 0;
$mm //= 0;
$_ = sprintf "%03d:%02d:%05.2f|%s", $hh, $mm, $ss, $_;
}
print;
}
Учитывая входные данные:
cpu time 9.05 seconds
real time 8:02.07
cpu time 2:25.23
real time 1:39:44.15
cpu time 25.23 seconds
real time 39:44.15
cpu time 5.23 seconds
real time 44.15 seconds
real time 1:44.15
real time 1:04.15
real time 21:04.15
real time 1:01:04.15
real time 32:21:04.15
real time 122:21:04.15
Это генерирует выходные данные:
000:00:09.05|cpu time 9.05 seconds
000:08:02.07|real time 8:02.07
000:02:25.23|cpu time 2:25.23
001:39:44.15|real time 1:39:44.15
000:00:25.23|cpu time 25.23 seconds
000:39:44.15|real time 39:44.15
000:00:05.23|cpu time 5.23 seconds
000:00:44.15|real time 44.15 seconds
000:01:44.15|real time 1:44.15
000:01:04.15|real time 1:04.15
000:21:04.15|real time 21:04.15
001:01:04.15|real time 1:01:04.15
032:21:04.15|real time 32:21:04.15
122:21:04.15|real time 122:21:04.15
Что можно передать в простой sort
, чтобы получить:
000:00:05.23|cpu time 5.23 seconds
000:00:09.05|cpu time 9.05 seconds
000:00:25.23|cpu time 25.23 seconds
000:00:44.15|real time 44.15 seconds
000:01:04.15|real time 1:04.15
000:01:44.15|real time 1:44.15
000:02:25.23|cpu time 2:25.23
000:08:02.07|real time 8:02.07
000:21:04.15|real time 21:04.15
000:39:44.15|real time 39:44.15
001:01:04.15|real time 1:01:04.15
001:39:44.15|real time 1:39:44.15
032:21:04.15|real time 32:21:04.15
122:21:04.15|real time 122:21:04.15
И из которого столбец сортировки можно удалить с помощью «sed», чтобы получить:
cpu time 5.23 seconds
cpu time 9.05 seconds
cpu time 25.23 seconds
real time 44.15 seconds
real time 1:04.15
real time 1:44.15
cpu time 2:25.23
real time 8:02.07
real time 21:04.15
real time 39:44.15
real time 1:01:04.15
real time 1:39:44.15
real time 32:21:04.15
real time 122:21:04.15
Итак, учитывая, что файл данных — «xx.data», а сценарий Perl — xx.pl, командная строка выглядит так:
perl xx.pl xx.data | sort | sed 's/^[^|]*|//'
person
Jonathan Leffler
schedule
16.12.2010