我正在尝试将文本解析为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开始)。
我想要的是,对于135 / udp的行(或版本字段为空白的任何地方),捕获组4为空/ null。
似乎我的上一个.*
不应该通过行终止符,但确实如此。我还在最后一个捕获组之后包含?
以尝试使其成为可选项,如同允许空值一样。
有谁可以指出我做错了什么?解释我的错误而不仅仅是为我提供一个有效的正则表达式会更有帮助。
答案 0 :(得分:1)
\s
似乎与换行符匹配。这对我来说是意想不到的 - 我原本希望\s
只匹配空格。
仅尝试匹配制表符和空格:
[ \t]
代替\s
。
并且要求更高 - 意味着设置+
预期的空格和非空格,而不是*
:
(\d{1,5})\/(tcp|udp)[ \t]+open[ \t]+(\S+)[ \t]+(.*)
(\S+)
是打开和空格后预期的一个条目。
但是,因为我们只对那之后继续的那些线感兴趣:
[ \t]+
要求在该条目之后有空格(不包括那里结束的行) - (.*)
捕获空间之后的所有内容。
答案 1 :(得分:0)
正如bytepusher所指出的,我有一个匹配换行符的\ s。我用空格或制表符[\ t]的显式匹配替换了\ s,如:
(\d{1,5})\/(tcp|udp)\s+open\s+(\S+)[ \t]*(.*)?
最正确的是,我用预期间隔字符的显式匹配替换了/ s的所有实例:
(\d{1,5})\/(tcp|udp)[ \t]+open[ \t]+(\S+)[ \t]*(.*)?