AWK: сравнивать даты apache без использования регулярных выражений - PullRequest
2 голосов
/ 16 мая 2010

Я пишу приложение для анализа и хотел получить записи журнала Apache между двумя определенными датами. Предположим, что дата составлена ​​так: 22 декабря 2009 года: 00:19 (день / месяц / год: час: минута)

В настоящее время я использую регулярное выражение для замены названия месяца его числовым значением, удаления разделителей, поэтому приведенная выше дата преобразуется в: 221220090019, что делает сравнение даты тривиальным .. но ..

Выполнение регулярного выражения для каждой записи для больших файлов, скажем, одного, содержащего четверть миллиона записей, является чрезвычайно дорогостоящим ... Есть ли другой метод, не связанный с заменой регулярного выражения?

Заранее спасибо

Редактировать: вот функция преобразования / сравнения

function dateInRange(t, from, to) {
    sub(/[[]/, "", t);
    split(t, a, "[/:]");
    match("JanFebMarAprMayJunJulAugSepOctNovDec", a[2]);
    a[2] = sprintf("%02d", (RSTART + 2) / 3);
    s = a[3] a[2] a[1] a[4] a[5];

    return s >= from && s <= to;
}

«от» и «до» - интервалы в вышеупомянутом формате, а «t» - необработанное поле даты / времени в журнале apache (например, [22 / Dec / 2009: 00: 19: 36)

Ответы [ 4 ]

0 голосов
/ 17 мая 2010

Отбор файлов только для определения диапазона звучит немного тяжело для такой простой задачи (хотя двоичный поиск заслуживает внимания)

вот моя измененная функция, которая, очевидно, намного быстрее, поскольку регулярное выражение исключено

BEGIN {
    months["Jan"] = 1
    months["Feb"] = 2
    ....
    months["Dec"] = 12
}
function dateInRange(t, from, to) {
    split(t, a, "[/:]");
    m = sprintf("%02d", months[a[2]]);
    s = a[3] m a[1] a[4] a[5];
    ok = s >= from && s <= to;
    if(!ok && seen == 1){exit;}
    return ok;
}

Массив определяется и впоследствии используется для индексации месяцев. Гарантируется, что программа не продолжит проверять записи, когда дата выходит за пределы диапазона (переменная увидено установлена ​​при первом совпадении)

Спасибо всем за ваш вклад.

0 голосов
/ 16 мая 2010

Ну, вот идея, предполагая, что записи в журнале упорядочены по дате.

Вместо запуска регулярного выражения в каждой строке файла и проверки, находится ли эта запись в требуемом диапазоне, выполните двоичный поиск .

Получить общее количество строк в файле. Прочитайте строку из середины и проверьте ее дату. Если он старше вашего диапазона - тогда все, что находится перед этой строкой, может быть проигнорировано. Разделите то, что осталось пополам, и снова проверьте линию от середины. И так до тех пор, пока не найдете границы своего диапазона.

0 голосов
/ 16 мая 2010

Вот программа на Python, которую я написал для выполнения двоичного поиска по файлу журнала на основе дат. Он может быть адаптирован для работы для вашего использования.

Он ищет середину файла, затем синхронизируется с новой строкой, читает и сравнивает дату, повторяет процесс, разбивая предыдущую половину пополам, делая это до совпадения даты (больше или равного), перематывая, чтобы убедиться, что с той же датой больше нет, затем считывает и выводит строки до конца желаемого диапазона. Это очень быстро.

У меня есть более продвинутая версия в работе. В конце концов я закончу и выложу обновленную версию.

0 голосов
/ 16 мая 2010

Однажды у меня была та же проблема очень медленной программы на AWK, которая включала регулярные выражения. Когда я перевел всю программу на Perl, она работала с гораздо большей скоростью. Я думаю, это потому, что GNU AWK компилирует регулярное выражение каждый раз, когда интерпретирует выражение, где perl просто компилирует выражение один раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...