RegExp для соответствия дате и времени из пользовательского файла журнала

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

Мой файл журнала имеет формат:

2012-11-06 10:32:45
<log message follows here on multiple lines in XML format> 

Я использую следующее выражение gawk для преобразования моей даты/времени в метку времени:

$ gawk '/^([0-9]{2,4}-?){3} ([0-9]{2}\:?){3}/{print $0;gsub(/\:/," ");print mktime($0)}' logfile.txt

Вывод будет:

2012-11-01 15:27:28
1293719248

На самом деле это то, что я ищу, но вопрос в том, правильно ли регулярное выражение? Поскольку я далек от мастера регулярных выражений, я тоже хотел бы знать, нормально это или нет. Можно ли это сделать более причудливым образом, когда дело доходит до регулярного выражения? Формат, используемый в файле журнала, никогда не изменится, потому что я не удосужился сделать универсальное совпадение даты и времени. Может еще что-то в моем выражении фубар? :-)


person Qben    schedule 06.11.2012    source источник


Ответы (3)


если вы работаете только с файлом журнала, с регулярным выражением все в порядке. Потому что вы можете предположить, что ваш файл журнала всегда будет давать действительную строку даты и времени. (например, 2012-13-56 28:23:77 не произойдет)

Но я хочу отметить, что у ваших кодов awk могут быть проблемы.

  • Я не знаю, какую версию gawk вы используете (полагаю, > 4.0), опция --re-interval не используется по умолчанию, если версия ‹ 4.

  • В вашей замене строки есть ошибка: вы также должны заменить "-" на " ", верно?

справочная страница awk:

 mktime(datespec)
                 Turns datespec into a time stamp of the same form as returned by systime().  The datespec is a string of the form YYYY MM DD HH  MM  SS[  DST].

увидеть разницу:

kent$  gawk '{print $0;gsub(/:|-/," ");print mktime($0)}' <<<"2012-11-01 15:27:28"
2012-11-01 15:27:28
1351780048

output with your awk line:
2012-11-01 15:27:28
1293719248
person Kent    schedule 06.11.2012
comment
Да, я использую 4.0.1. Ага, хорошее замечание (и интересное)! Поскольку мой ввод сгенерировал метку времени, а не -1, я решил, что он проглотил часть даты, включая - правильно. Я прочитал справочную страницу, но был ленив и глуп и проигнорировал - на основе предыдущего утверждения. :) Спасибо. - person Qben; 06.11.2012

ERE для соответствия:

2012-11-06 10:32:45

на отдельной строке:

^[[:digit:]]{4}(-[[:digit:]]{2}){2} [[:digit:]]{2}(:[[:digit:]]{2}){2}$

но вы, вероятно, могли бы уйти с:

^[[:digit:]]([[:digit:]: -][[:digit:]]{2}){6}$

без получения ложных совпадений.

person Ed Morton    schedule 06.11.2012
comment
+1 - это совершенно правильно. Обратите внимание, что большинство реализаций регулярных выражений позволяют использовать \d в качестве сокращения для [:digit:]. - person ghoti; 07.11.2012

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

awk '{ line = $0; gsub(/[:-]/, " "); time = mktime($0) } time != "-1" { print line ORS time }' file.txt

Результат:

2012-11-06 10:32:45
1352161965

Со страницы руководства:

If datespec does not contain enough elements or if the resulting time is out of 
range, mktime() returns −1.
person Steve    schedule 06.11.2012
comment
Это довольно умно, я поставлю +1, потому что это показывает другой подход к проблеме. Из любопытства будет ли влияние на производительность больше при этом? - person Qben; 06.11.2012
comment
@Qben: В моем тестировании это на самом деле быстрее, чем метод регулярных выражений, который вы описываете (даже если я рассматриваю ответ Кента и сокращаю ваши два оператора печати до одного). Этот метод по-прежнему занимает всего две трети времени, которое занимает ваш. Интересно эй. - person Steve; 07.11.2012
comment
Это действительно интересно. Я предполагаю, что у людей, которые написали mktime(), есть лучшее/более оптимизированное регулярное выражение, чем у меня. :-) - person Qben; 07.11.2012