Изменить формат даты с помощью awk - PullRequest
1 голос
/ 28 марта 2019

У меня есть файл журнала, я пытаюсь переформатировать с использованием sed / awk / grep, но сталкиваюсь с трудностями с форматом даты. Лог выглядит так:

1.2.3.4 - - [28/Mar/2019:11:43:58 +0000] "GET /e9bb2dddd28b/5.6.7.8/YL0000000000.rom HTTP/1.1" "-" "Yealink W52P 25.81.0.10 00:00:00:00:00:00" 404 - 1 5 0.146

Я бы хотел, чтобы вывод был таким:

Yealink,1.2.3.4,28-03-2019 11:43:58

Я пробовал следующее:

grep Yealink access.log | grep 404 | sed 's/\[//g' | awk '{print "Yealink,",$1,",",strftime("%Y-%m-%d %H:%M:%S", $4)}' | sed 's/, /,/g' | sed 's/ ,/,/g'

edit - удаление [ перед передачей строки даты в strftime на основе комментариев - но все еще не работает, как ожидалось

Однако это возвращает нулевую дату - так ясно, что у меня неправильный синтаксис strftime:

Yealink,1.2.3.4,1970-01-01 01:00:00

Ответы [ 2 ]

1 голос
/ 28 марта 2019

См. руководство gawk для strftime, оно не ожидает времени в любом формате, кроме секунд с начала эпохи. Если бы у gawk была str p time () THEN, это сработало бы, но это не сработало (и Я не могу убедить сопровождающих предоставить один ), поэтому вам нужно помассировать метка времени в формат, который mktime () может преобразовать в секунды, а затем передать TH в strftime (), например:

$ awk '{
    split($4,t,/[[\/:]/)
    old  = t[4] " " (index("JanFebMarAprMayJunJulAugSepOctNovDec",t[3])+2)/3 " " t[2] " " t[5] " " t[6] " " t[7];
    secs = mktime(old)
    new  = strftime("%d-%m-%Y %T",secs);
    print $4 ORS old ORS secs ORS new
}' file
[28/Mar/2019:11:43:58
2019 3 28 11 43 58
1553791438
28-03-2019 11:43:58

но, конечно, вам вообще не нужны mktime () или strftime () - просто перетасуйте компоненты даты вокруг:

$ awk '{
    split($4,t,/[[\/:]/)
    new = sprintf("%02d-%02d-%04d %02d:%02d:%02d",t[2],(index("JanFebMarAprMayJunJulAugSepOctNovDec",t[3])+2)/3,t[4],t[5],t[6],t[7])
    print $4 ORS new
}' file
[28/Mar/2019:11:43:58
28-03-2019 11:43:58

Это будет работать в любом awk, а не только в GNU awk, поскольку оно не требует функций времени.

index("JanFebMarAprMayJunJulAugSepOctNovDec",t[3])+2)/3 - это просто идиоматический способ преобразования трехмесячной аббревиатуры названия месяца (например, Mar) в эквивалентный номер месяца (3).

0 голосов
/ 28 марта 2019

Еще один awk, спасибо @EdMorton за просмотр использования getline.

Идея состоит в том, чтобы использовать команду date в awk, которая принимает сокращенные месяцы

$ date -d"28/Mar/2019:11:43:58 +0000" "+%F %T"  # Fails
date: invalid date ‘28/Mar/2019:11:43:58 +0000’
$ date -d"28 Mar 2019:11:43:58 +0000" "+%F %T"  # Again fails because of : before time section
date: invalid date ‘28 Mar 2019:11:43:58 +0000’
$ date -d"28 Mar 2019 11:43:58 +0000" "+%F %T" # date command works but incorrect time because of + in the zone
2019-03-28 17:13:58
$ date -d"28 Mar 2019 11:43:58" "+%F %T" # correct value after stripping +0000
2019-03-28 11:43:58
$

Результаты

awk -F"[][]" -v OFS=, '/Yealink/ { 
split($1,a," ");              #Format $1 to get IP
gsub("/", " ",$2); sub(":"," ",$2); sub("\\+[0-9]+","",$2); # Massage to get data value
cmd = "date -d\047" $2 "\047 \047+%F %T\047"; if ( (cmd | getline line) > 0 ) $2=line; close(cmd) # use system date
print "Yealink",a[1],$2 
} ' access.log

Ниже приведено содержимое файла

$ cat access.log
1.2.3.4 - - [28/Mar/2019:11:43:58 +0000] "GET /e9bb2dddd28b/5.6.7.8/YL0000000000.rom HTTP/1.1" "-" "Yealink W52P 25.81.0.10 00:00:00:00:00:00" 404 - 1 5 0.146
$
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...