Метка: Parse

ParseExact

Прочитал у Василия Гусева статью get-dhcpclients и очень мне захотелось самому распарсить какой-нибудь лог. Естественно повезло мне с первого раза, нужно было распарсить такую вот строчку, дальше всё повторялось за исключением времени, ip и не найденного файла.

[Fri Jul 22 10:15:16 2005] [error] [client 192.168.145.194] File does not exist: z:/home/zorion/www/admincp/

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

[Fri Jul 22 10:15:16 2005]

Парсинг строки очень простой

«^(\[)(\S+ \S+ \d{2} \d{2}:\d{2}:\d{2} \d{4})(\])«

Вот комментарии написанные Василием, думаю по ним всё понятно

# Некоторые пояснения к выражению:

# ^ – Начало строки

# \d – 1 цифра

# \d{1,3} – от 1 до 3х цифр

# . – 1 любой символ

# \. – точка, просто точка.

# .+ – 1 или более любых символов

# (?:..-){5} – последовательность из двух любых символов и тире, повторенная 5 раз.

# Все групы попадающие в круглые скобки помещаются в массив $Matches под индексами 1,2 и тд.

Разберу для моего примера всю строку и не забываем что пробел означает пробел ;-)

^ – Начало строки

(\[) – символ [“, скобки ( ) нужны для того чтобы парсер знал, что скобка будет храниться в $Matches[1]

(\S+ \S+Fri Jul, скобка означает что начался кусок $Matches[2]

\d{2} – Две цифры 22

\d{2}:\d{2}:\d{2} 10:15:16

\d{4}) – Год 2005 и скобка, означающая что $Matches[2] закончился

“(\])” – Последний символ ]

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

«ddd MMM dd HH:mm:ss yyyy«

ddd – День недели, три буквы

MMM – Месяц, три буквы, ну и так далее

Но система у меня русская и про Fri и Jul она ни чего не знает. Так что для того чтобы распарсить эту строку, нужно либо заменить все английские слова на русские либо указать что мы используем английскую систему дат. Первое отмёл сразу, слишком муторно, второе отняло пол дня, ну не программист я. Как только не эксперементировал, понял одно, что есть принцип. Parseexact(Строка,”Маска”,”и что-то ещё”). Всё-таки нашёл, вместо en-US можно подставлять любой язык известный Windows.

[datetime]::parseexact(«Fri Jul 22 10:15:16 2005«,«ddd MMM dd HH:mm:ss yyyy«,` [System.Globalization.CultureInfo]::CreateSpecificCulture(«en-US«))

Вот что получилось в итоге.

# Берём лог # f:\denver\home\zorion\error-test.log

$us = [System.Globalization.CultureInfo]::CreateSpecificCulture(«en-US«)

$Pattern = «^(\[)(\S+ \S+ \d{2} \d{2}:\d{2}:\d{2} \d{4})(\])«

Get-Content f:\denver\home\zorion\error-test.log |

Where-Object {$_ -match $Pattern} |

select @{Name = «Data«; Expression = {[datetime]::parseexact($matches[2],«ddd MMM dd HH:mm:ss yyyy«,$us)}}

Если кому что-то не понятно, с удовольствием отвечу.