регулярное выражение python. этот код не может прочитать 2-ю строку, в которой имя пользователя указано только как «-«

#python #regex #verbose

Вопрос:

Я пытаюсь получить словарь различных ключей следующим образом. проблема в том, что этот код пропускает 2 — ю строку, в которой есть имя пользователя другого типа .т. е. имя пользователя = — также в последней строке, которую я вижу, изначально есть место перед хостом.не могли бы вы помочь разобраться в проблеме?

 import re
def logs():
    logdata = """146.204.224.152 - feest6811 [21/Jun/2019:15:45:24 -0700] "POST /incentivize HTTP/1.1" 302 4622
    159.253.153.40 - - [21/Jun/2019:15:46:10 -0700] "POST /e-business HTTP/1.0" 504 19845
    197.109.77.178 - kertzmann3129 [21/Jun/2019:15:45:25 -0700] "DELETE /virtual/solutions/target/web services HTTP/2.0" 203 26554"""
 

 # YOUR CODE HERE
pattern="""  
(?P<host>.*)
( - )
(?P<user_name>w.*)
( [)
(?P<time>.*)
(] ")
(?P<request>w.*)
(")    
"""


for item in re.finditer(pattern,logdata,re.VERBOSE):
    print(item.groupdict())
return
 

Ответ №1:

Вы ищете только имена пользователей, состоящие из слов, но » — » — это не слово.

Если вы измените регулярное выражение на:

 pattern="""  
(?P<host>.*)
( - )
(?P<user_name>(w.*|-))
( [)
(?P<time>.*)
(] ")
(?P<request>w.*)
(")    
"""
 

Вы будете искать либо слова, либо» -»

Ответ №2:

Вы можете сделать шаблон немного более конкретным, не используя .* , который сначала будет совпадать до конца строки, а затем может вернуться, чтобы соответствовать следующим частям шаблона, чтобы получить общее совпадение.

Поскольку формат журналов кажется одинаковым, вы можете сопоставить хост и имя пользователя, соответствующие 1 символам без пробелов, используя S , как представляется, пробелы отсутствуют.

Конечно, вы также можете сделать детали более конкретными, чтобы они соответствовали ip-номеру хоста и времени, подобному шаблону для времени.

 (?P<host>S ) - (?P<user_name>S ) [(?P<time>[^][]*)] "(?P<request>w[^"]*)"
 

По частям шаблон совпадает:

  • (?P<host>S ) Группа host , совпадение 1 символов без пробелов
  • - Совпадение буквально
  • (?P<user_name>S ) Группа user_name соответствует 1 символам без пробелов и пробелу
  • [(?P<time>[^][]*)] Групповое time соответствие все в квадратных скобках
  • "(?P<request>w[^"]*)" Групповое request совпадение всех между двойными кавычками

Демонстрация регулярных выражений

Например, без re.VERBOSE флага

 import re

def logs():
    logdata = """146.204.224.152 - feest6811 [21/Jun/2019:15:45:24 -0700] "POST /incentivize HTTP/1.1" 302 4622
    159.253.153.40 - - [21/Jun/2019:15:46:10 -0700] "POST /e-business HTTP/1.0" 504 19845
    197.109.77.178 - kertzmann3129 [21/Jun/2019:15:45:25 -0700] "DELETE /virtual/solutions/target/web services HTTP/2.0" 203 26554"""
    pattern = '(?P<host>S ) - (?P<user_name>S ) [(?P<time>[^][]*)] "(?P<request>w[^"]*)"'

    for item in re.finditer(pattern, logdata):
        print(item.groupdict())
logs()
 

Выход

 {'host': '146.204.224.152', 'user_name': 'feest6811', 'time': '21/Jun/2019:15:45:24 -0700', 'request': 'POST /incentivize HTTP/1.1'}
{'host': '159.253.153.40', 'user_name': '-', 'time': '21/Jun/2019:15:46:10 -0700', 'request': 'POST /e-business HTTP/1.0'} 
{'host': '197.109.77.178', 'user_name': 'kertzmann3129', 'time': '21/Jun/2019:15:45:25 -0700', 'request': 'DELETE /virtual/solutions/target/web services HTTP/2.0'}