Найти все вхождения шаблона в текстовом файле

#python #regex

#python #регулярное выражение

Вопрос:

У меня есть текстовый файл, который выглядит следующим образом

 Nmap scan report for 192.168.2.1
Host is up (0.023s latency).
PORT     STATE  SERVICE
5001/tcp closed commplex-link
MAC Address: EC:1A:59:A2:84:80 (Belkin International)

Nmap scan report for 192.168.2.2
Host is up (0.053s latency).
PORT     STATE  SERVICE
5001/tcp closed commplex-link
MAC Address: 94:35:0A:F0:47:C2 (Samsung Electronics Co.)

Nmap scan report for 192.168.2.3  
Host is up (0.18s latency).  
PORT     STATE    SERVICE  
5001/tcp filtered commplex-link  
MAC Address: 00:13:CE:C0:E5:F3 (Intel Corporate)  

Nmap scan report for 192.168.2.6
Host is up (0.062s latency).
PORT     STATE  SERVICE
5001/tcp closed commplex-link
MAC Address: 90:21:55:7D:53:4F (HTC)
 

Я хочу найти все IP-адреса с закрытым портом 5001 (не фильтруется). Я попытался использовать следующую логику для поиска всех таких IP-адресов

 fp = open('nmap_op.txt').read()
ip = re.compile('([0-9] .[0-9] .[0-9] .[0-9] )(.*)closed',re.S)
matched = ip.findall(fp)
for item in matched:
  print item
 

Я ожидал, что результат будет

192.168.2.1

192.168.2.2

192.168.2.6

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

(‘192.168.2.1’, ‘nHost запущен (задержка 0,023 с).NPort STATE SERVICE n5001 / tcp закрытая коммутационная связь nMAC Адрес: EC: 1A: 59: A2:84:80 (Belkin International) n Отчет о проверке nNmap для 192.168.2.2 nHost запущен (задержка 0,053 с).Служба СОСТОЯНИЯ NPort n5001 / tcp закрыла коммутационную связь nMAC Адрес: 94:35:0A: F0:47:C2 (Samsung Electronics Co.) n Отчет о сканировании nNmap для 192.168.2.3 nHost запущен (задержка 0,18 с).NPort STATE SERVICE n5001 / tcp filtered commplex-link nMAC Адрес: 00:13: CE: C0: E5: F3 (корпорация Intel) n Отчет о проверке nNmap для 192.168.2.6 nHost запущен (задержка 0,062 с).СЛУЖБА СОСТОЯНИЯ NPort n5001 / tcp )

Где я ошибаюсь?

Решение: приведенная ниже логика сработала для меня. Если у кого-нибудь есть лучший ответ, пожалуйста, дайте мне знать.

 fp = open('nmap_op.txt').read()
entries = re.split('nn',fp)  
ip = re.compile('([0-9] .[0-9] .[0-9] .[0-9] ).*?closed',re.S)
matched = []
for item in entries:
  if ip.search(item):
    matched.append(ip.search(item).group(1))
 

Комментарии:

1. 1 для включенного соответствующего кода, ожидаемого результата и фактического результата

Ответ №1:

Здесь вам это не нужно re.S . s Модификатор изменяет значение метасимвола dot ( . ) с «сопоставлять все, кроме символов новой строки», на «сопоставлять все, включая символы новой строки». Здесь это не нужно.

Вторая группа захвата также не требуется. Вы можете просто удалить его, чтобы возвращались только IP-адреса:

 >>> matched = re.findall('([0-9] .[0-9] .[0-9] .[0-9] ).*closed', fp)
>>> matched
['192.168.2.1', '192.168.2.2', '192.168.2.6']
 

Комментарии:

1. Спасибо за ваш ответ, Амаль. На самом деле IP-адрес и 5001 / tcp closed находятся в разных строках. Я заметил, что неправильно задал формат текстового файла. Извините за это. Я использовал новый шаблон ip = re.compile(‘([0-9] .[0-9] .[0-9] .[0-9] ).*? закрыто’, re.S) при этом я получаю вывод как [‘192.168.2.1’, ‘192.168.2.2’,’192.168.2.3′] Последняя запись неверна, и я думаю, даже вы понимаете, почему. Я приближаюсь. Мне просто нужен шаблон, который будет игнорировать IP, если он видит шаблон как «отфильтрованный» между ними. Можете ли вы помочь мне с этим?

Ответ №2:

Поскольку формат строк, по-видимому, всегда одинаков (ip начинается со смещения 21 и заканчивается следующим пробелом), вы можете попробовать это другим способом без регулярных выражений:

 for block in data.split("nn"):
    if block.find('5001/tcp closed')>0:
        print block[21:block.find('n', 27)]
 

Комментарии:

1. Привет, Казимир. Спасибо за ваш ответ. На самом деле IP-адрес и 5001 / tcp closed находятся в разных строках. Я заметил, что неправильно задал формат текстового файла. Извините за это. Я исправил формат текстового файла. Мне понравилась ваша идея. Я тоже думаю об этой строке

2. @Sanket: Я вижу, это не имеет значения, я уверен, что есть более эффективный способ, чем использование регулярного выражения для вашего конкретного случая, поскольку ваши данные четко отформатированы (или, по крайней мере, более простой шаблон)

Ответ №3:

Вы можете сделать:

 >>> re.findall(r'^Nmap.*?(d .d .d .d ).*?5001/tcp closed', fp, re.M)
# ['192.168.2.1', '192.168.2.2', '192.168.2.6']
 

Ответ №4:

Решение: приведенная ниже логика сработала для меня.

 fp = open('nmap_op.txt').read()
entries = re.split('nn',fp)  
ip = re.compile('([0-9] .[0-9] .[0-9] .[0-9] ).*?closed',re.S)
matched = []
for item in entries:
  if ip.search(item):
    matched.append(ip.search(item).group(1))