Как сортировать по чч:мм:сс.хх в ksh в AIX 5.3?

У меня есть много файлов журнала, как это:


......
......
процессорное время 9,05 секунды
реальное время 8:02.07
......
......
время процессора 2:25,23
реальное время 1:39:44,15
......
......


Чтобы получить все значения времени, я просто выполняю grep для всего времени ЦП и реального времени.
Затем сортирую выходные файлы grep.
Я использую AIX 5.2, там есть сортировка по строке или по числовому числу.
Но , нет сортировки по часам:минутам:секундам.

Чтобы решить эту проблему, я передаю строки вывода grep в цикл while.
Затем создаю новые переменные, используя sed 's/:/00/g'
Эта новая переменная сделает чч:мм:сс .xx становится hh00mm00ss.xx
, а затем сортируется по этой новой переменной как числовой.

Используя этот способ, я могу найти самые трудоемкие шаги.
Этот обходной путь может работать, но скорость немного медленная.

Может у кого есть лучшая альтернатива?
Заранее спасибо.

Элвин SIU


person Alvin SIU    schedule 16.12.2010    source источник


Ответы (2)


В статье «Теория и практика построения рабочей процедуры сортировки» Дж. П. Линдерман показывает, что лучший способ получить хорошую производительность от системной команды 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
comment
Да, мне нужно сохранить контекст строки. Ты читаешь мои мысли. Спасибо. - person Alvin SIU; 23.12.2010

Если вы покажете свой сценарий, это поможет, однако я подозреваю, что цикл while не нужен. Попробуйте что-то вроде этого:

grep -E '^(cpu|real) time' | sed 's/:/00/' | sort -n
person Dennis Williamson    schedule 16.12.2010