Для анализа логов nginx мне понадобилось регулярное выражение, которое бы корректно разделяло запись на отдельные поля. Немного по-колдовав над логом, я понял, что наилучший способ разобраться в формате лога - это выцепить его из конфигурации сервера.
Кроме очевидного плюса - выделение полей с учетом всех разделителей и кавычек, использование формата позволяет получить именованные поля.
Вот код, который у меня получился, возможно пригодится.
import re
# формат из конфигурации nginx
FORMAT = '$remote_addr - $remote_user [$time_local] "$request" $status' + \
' $bytes_sent "$http_referer"' + \
' "$http_user_agent" "$gzip_ratio" "$cookie" $hostname'
# выражение, описывающее переменную в конфигурации логов nginx
TOKEN = '\$([a-z\_]+)'
# возможные скобки и кавычки вокруг переменных в конфигурации логов nginx
POSSIBLE_QUOTES = ('[]', '"', '\'')
def get_matcher(format):
quotes = re.escape(''.join(POSSIBLE_QUOTES))
pat = format
for token in re.findall(TOKEN, format):
res = re.search('([%s]?)(\$%s)([%s]?)' % \
(quotes, token, quotes), format).groups()
if not res:
continue
elif res[0] <> res[2]:
tq = res[0] + res[2]
tq_escaped = '\%s|\%s' % (res[0], res[2])
else:
tq = res[0]
tq_escaped = '\%s' % res[0]
tq = re.escape(tq)
tq_escaped = re.escape(tq_escaped)
if not tq:
ftoken = '\$%s' % (token)
ptoken = '(?P<' + token + '>[^\ ]*)'
else:
ftoken = '[%s]\$%s[%s]' % (tq, token, tq)
ptoken = '[%s](?P<%s>(?:%s|[^%s])*)[%s]' % (tq, token, tq_escaped, tq, tq)
pat = re.sub(ftoken, ptoken, pat)
patc = re.compile(pat)
def matcher(line):
return patc.match(line)
return matcher
def main():
f = file('access_log')
matcher = get_matcher(FORMAT)
for line in f:
print matcher(line).groupdict()
Возможно кому-нибудь будет полезным
UPD: Немного поправил код, чтобы он корректно работал с записями, в которых встречаются поля вида: “some text with escaped \” qoute”
--
Этот, а также другие мои посты по it-тематике вы можете прочитать
здесь