Запуск команд оболочки в AWK - PullRequest
3 голосов
/ 04 мая 2011

Я пытаюсь работать с лог-файлом, и мне нужно иметь возможность указать диапазон дат.Пока (до какой-либо обработки) я конвертирую строку даты / времени в метку времени, используя date --date "monday" +%s.

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

echo `awk '{if(`date --date "$3 $4 $5 $6 $7" +%s` > $START && `date --date "" +%s` <= $END){/*processing code here*/}}' myfile`

Я даже не знаю, возможно ли это ... Я перепробовал много вариантов, плюс я не могнайти что-нибудь понятное / пригодное для использования в Интернете.

Спасибо

Обновление:

Пример файла myfile следующий.Его IP-адреса регистрации и время доступа:

123.80.114.20      Sun May 01 11:52:28 GMT 2011
144.124.67.139     Sun May 01 16:11:31 GMT 2011
178.221.138.12     Mon May 02 08:59:23 GMT 2011

Ответы [ 3 ]

1 голос
/ 04 мая 2011

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

Вот частичное решение, которое использует ассоциативные массивы для преобразования значения месяца в число. Затем вы полагаетесь на спецификатор формата% 02d, чтобы обеспечить 2 цифры. Вы можете переформатировать значение dateTime с помощью '.' И т. Д. Или оставить двоеточия в часах: мин: сек, если вам действительно нужна читабельность.

Формат YYYYMMDD очень помогает в решении подобных проблем, поскольку LT, GT, EQ работают без какого-либо дополнительного форматирования.

echo "178.221.138.12     Mon May 02 08:59:23 GMT 2011" \
| awk 'BEGIN {
mons["Jan"]=1 ; mons["Feb"]=2; mons["Mar"]=3
mons["Apr"]=4 ; mons["May"]=5; mons["Jun"]=6
mons["Jul"]=7 ; mons["Aug"]=8; mons["Sep"]=9
mons["Oct"]=10 ; mons["Nov"]=11; mons["Dec"]=12
}
{ 
   # 178.221.138.12     Mon May 02 08:59:23 GMT 2011
   printf("dateTime=%04d%02d%02d%02d%02d%02d\n", 
       $NF, mons[$3], $4, substr($5,1,2), substr($5,4,2), substr($5,7,2) )
} ' -v StartTime=20110105235959

Параметр -v StartTime иллюстрирует, как передать (и соответствующий формат) ваше значение starTime.

Надеюсь, это поможет.

1 голос
/ 04 мая 2011

Вот альтернативный подход, использующий встроенную функцию awk mktime (). До сих пор я никогда не беспокоился о разборе месяца - спасибо приюту за эту часть (см. Принятый ответ). Всегда есть время переключать язык вокруг этой точки.

#!/bin/bash
# input format:
#(1                  2   3   4  5        6   7)
#123.80.114.20      Sun May 01 11:52:28 GMT 2011

awk -v startTime=1304252691 -v endTime=1306000000 '
BEGIN {
  mons["Jan"]=1 ; mons["Feb"]=2; mons["Mar"]=3
  mons["Apr"]=4 ; mons["May"]=5; mons["Jun"]=6
  mons["Jul"]=7 ; mons["Aug"]=8; mons["Sep"]=9
  mons["Oct"]=10 ; mons["Nov"]=11; mons["Dec"]=12;
}
{
  hmsSpaced=$5; gsub(":"," ",hmsSpaced); 
  timeInSec=mktime($7" "mons[$3]" "$4" "hmsSpaced); 
  if (timeInSec > startTime && timeInSec <= endTime) print $0
}' myfile

(я выбрал примерные пороги времени, чтобы выбрать только последние две строки журнала.)

Обратите внимание, что если бы функция mktime() была немного умнее, все это уменьшилось бы до:

awk -v startTime=1304252691 -v endTime=1306000000 't=mktime($7" "$3" "$4" "$5); if (t > startTime && t <= endTime) print $0}' myfile
0 голосов
/ 04 мая 2011

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

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