Когда это было впервые опубликовано, регулярное выражение выглядело так:
p = re.compile(r'''(?P<ip>\d+(\.\d+){3}) - - \[(?P<date_time>.+?)\] (?P<method>\".+?\") \
(?P<response_code>\d+) \d+ "-" (?P<client>\".+?\")''')
Обратите внимание на символ продолжения строки ('\') в конце первой строки. Но шаблон также в тройных кавычках. Таким образом, шаблон включает в себя текст '\\n '
(косая черта + новая строка + отступ). В результате шаблон не будет совпадать.
Перепишите шаблон в одну строку, и он должен работать:
p = re.compile(r'''(?P<ip>\d+(\.\d+){3}) - - \[(?P<date_time>.+?)\] (?P<method>\".+?\") (?P<response_code>\d+) \d+ "-" (?P<client>\".+?\")''')
Для сложных регулярных выражений мне нравится использовать подробный режим:
regex = re.compile("""
(?P<ip>\d+(?:\.\d+){3}) # four, dot-separated sets of digits
.*? # skip ahead
\[(?P<date_time>.*?)\] # date time is everything between '[ ]'
.*? # skip
"(?P<method>.*?)" # method is everything between quotes
.*? # skip
(?P<response_code>\d+) # multiple digits
.*? # skip
"-" # don't care
.*? #
"(?P<client>.*?)" # client is everything between quotes
""", re.VERBOSE)
Еще несколько вещей:
Если вы ожидаете, что регулярное выражение будет совпадать (почти) с каждой строкой в журнале, вы должны напечатать / записать все строки, которые не совпадают. Это помогает отлавливать ошибки в вашем регулярном выражении или когда кто-то изменяет формат журнала, не сообщая вам.
Переместите шаг re.compile из цикла.
MatchObject.group()
может принимать несколько аргументов ивозвращает кортеж из перечисленных групп.
def parse_logs(logs):
log_list = []
p = re.compile(...whichever regex style you like...)
for log in logs:
m = p.search(log)
if m:
log_list.append(m.group('ip_addr', 'date_time', 'http_method,
'return_code', 'client'))
else:
print(log)
rdd_prepped = parse_logs(rdd.take(5))