Я тестирую регулярное выражение, необходимое для создания извлечения полей с помощью Splunk для nmap, и думаю, что я близок к цели...
Пример полной строки:
Host: 10.0.0.1 (host) Ports: 21/open|filtered/tcp//ftp///, 22/open/tcp//ssh//OpenSSH 5.9p1 Debian 5ubuntu1 (protocol 2.0)/, 23/closed/tcp//telnet///, 80/open/tcp//http//Apache httpd 2.2.22 ((Ubuntu))/, 10000/closed/tcp//snet-sensor-mgmt/// OS: Linux 2.6.32 - 3.2 Seq Index: 257 IP ID Seq: All zeros
Я использовал подчеркивание «_» в качестве разделителя, потому что это немного облегчает чтение.
root@host:/# sed -n -e 's_\([0-9]\{1,5\}\/[^/]*\/[^/]*\/\/[^/]*\/\/[^/]*\/.\)_\n\1_pg' filename
То же самое регулярное выражение с удаленными экранированными символами:
root@host:/# sed -n -e 's_\([0-9]\{1,5\}/[^/]*/[^/]*//[^/]*//[^/]*/.\)_\n\1_pg' filename
Выход:
... ... ...
Host: 10.0.0.1 (host) Ports:
21/open|filtered/tcp//ftp///,
22/open/tcp//ssh//OpenSSH 2.0p1 Debian 2ubuntu1 (protocol 2.0)/,
23/closed/tcp//telnet///,
80/open/tcp//http//Apache httpd 5.4.32 ((Ubuntu))/,
10000/closed/tcp//snet-sensor-mgmt/// OS: Linux 9.8.76 - 7.3 Seq Index: 257 IPID Seq: All zeros
... ... ...
Как вы видите, сопоставление с образцом, похоже, работает, хотя мне это не удается:
1 - сопоставить шаблон на обоих концах строки (запятая и пробел/табуляция). Последняя строка содержит нежелательный текст (в данном случае, информацию об ОС и синхронизации TCP). Логическое "ИЛИ" для двух символов (запятая и пробел) похоже не совпадает.
...(\,|\s)
и
2 - удалить все ненужные данные - т.е. напечатать только совпадающий шаблон. На самом деле это печать всей строки. Если я уберу флаг sed -n, оставшееся содержимое файла также будет напечатано. Я не могу найти способ напечатать только совпавшее регулярное выражение.
т.е. почему, когда я явно говорю не делать этого, sed печатает эти строки? =>
Host: 10.0.0.1 (host) Ports:
и
OS: Linux 2.6.32 - 3.2 Seq Index: 257 IP ID Seq: All zeros
Так как я новичок в sed и regex, любая помощь или указания будут высоко оценены!
решение1
Во-первых, я бы рекомендовал вам взглянуть на XML-вывод Nmap (доступный с флагом -oX
), который является официально поддерживаемым машиночитаемым форматом вывода. Вывод Greppable ( -oG
или .gnmap
) устарел, и поэтому не включает полезную информацию из новых функций Nmap, таких как traceroute и скрипты NSE.
Чтобы ответить на ваши вопросы напрямую,
проблема с сопоставлением запятой или пробела приводит к ошибкам, поскольку необходимо экранировать символ чередования (
|
), а не запятую. Кроме того, вы, вероятно, всегда хотите сопоставить символ пробела, но только иногда запятую. Вот как я бы это сделал:,\?\s
Я не использую группировку, так как нет чередования (или).
sed
не печатает «линии», которые вам не нужны, а печатает пространство шаблона.Страница информации sedобъясняет, как работает sed, и является отличным справочником по написанию скриптов sed. По сути, у вас есть 2 пространства для работы, и sed выведет все содержимое пространства шаблона, когда вы используете командуp
.
В качестве примера того, как это можно сделать, вот мой вариант скрипта sed для вывода только информации о порте из файла .gnmap
:
#!/usr/bin/sed -n
#First, strip the beginning (Host and Ports labels) off
s/.*Ports: //
#Now match a port entry, consuming the optional comma and whitespace
#The comma and whitespace are replaced with a newline
s_\([0-9]\{1,5\}/[^/]*/[^/]*/[^/]*/[^/]*/[^/]*/[^/]*/\),\?\s_\1\n_
#If we made a successful substitution, jump to :matched,
t matched
#otherwise skip to the next input line
d
:matched
#Print the pattern space up to the first newline
P
#Then delete up to the first newline and start over with what's left
D
Все вместе в одной строке это будет выглядеть примерно так:
sed -n -e 's/.*Ports: //;s_\([0-9]\{1,5\}/[^/]*/[^/]*/[^/]*/[^/]*/[^/]*/[^/]*/\),\?\s_\1\n_;t matched;d;:matched;P;D' file.gnmap
Обратите внимание также, что вы не можете рассчитывать на то, что некоторые поля в спецификации порта всегда будут пустыми. Если определение версии было выполнено, например, на службе RPC, поле информации SunRPC будет заполнено.