Как я могу исправить это регулярное выражение? (результаты Nmap)
Я пытаюсь разобрать текст в 4 группы захвата, но я столкнулся с проблемой.
Мое регулярное выражение:
(\d{1,5})\/(tcp|udp)\s+open\s+(\S+)\s*(.*)?
Некоторые примеры ввода:
Nmap scan report for X
Host is up (0.097s latency).
Not shown: 192 closed ports
PORT STATE SERVICE VERSION
135/udp open msrpc
137/udp open netbios-ns Microsoft Windows XP netbios-ssn (workgroup: THINC)
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
445/tcp open microsoft-ds Windows XP microsoft-ds
Это работает почти идеально. Проблема в строке 135/udp, поле версии отсутствует, поэтому моя группа захвата 4 для этой строки оборачивается и захватывает всю следующую строку (начиная с 137/udp).
Я хотел бы, чтобы группа захвата 4 была пустой / нулевой для строки 135/udp (или в любом месте, где поле версии пустое).
Похоже мой последний .*
не должен проходить через терминатор строки, но это так. Я также включил ?
после моей последней группы захвата, чтобы попытаться сделать это необязательным, например, чтобы разрешить нулевое значение.
Кто-нибудь может указать, что я делаю не так? Было бы более полезно объяснить мою ошибку, чем просто предоставить мне рабочее выражение.
2 ответа
\s
похоже, совпадают с новыми строками. Это неожиданно для меня - я бы ожидал \s
соответствовать только пробелам.
Вместо этого попробуйте сопоставить только табуляцию и пробелы:[ \t]
вместо \s
,
и быть немного более требовательным, то есть устанавливать пробелы и непространства, которые ожидаются с +
, не с *
:
(\d{1,5})\/(tcp|udp)[ \t]+open[ \t]+(\S+)[ \t]+(.*)
(\S+)
это одна запись ожидается после открытых и пробелов. Но так как нас интересуют только те строки, которые продолжаются после этого:[ \t]+
требует наличия пробела после этой записи (исключая строку, которая заканчивается там) - с (.*)
захватывая все, что приходит после пробела.
Как указал bytepusher, у меня был символ \s, который соответствовал символам новой строки. Я заменил \s явным соответствием для пробелов или табуляций [ \t], как в:
(\d{1,5})\/(tcp|udp)\s+open\s+(\S+)[ \t]*(.*)?
Наиболее правильно, я заменил все экземпляры /s с явными совпадениями для ожидаемых пробелов:
(\d{1,5})\/(tcp|udp)[ \t]+open[ \t]+(\S+)[ \t]*(.*)?