【发布时间】:2014-03-27 19:34:06
【问题描述】:
假设我想从这样的字符串中提取主机名和端口号:
stackoverflow.com:443
这很容易。我可以这样做:
(?<host>.*):(?<port>\d*)
我不担心协议方案或有效的主机名/IP 地址或 tcp/udp 端口,这对我的请求并不重要。
但是,我还需要支持一个超出我对正则表达式知识范围的扭曲 - 没有端口的主机名:
stackoverflow.com
我想为此使用单个正则表达式,并且我想使用命名捕获组,这样主机组将始终存在于正匹配中,而端口组存在当且仅当我们有一个冒号后跟几位数字。
我试图从我对它的微弱理解中做出积极的回顾:
(?<host>.*)(?<=:)(?<port>\d*)
这很接近,但冒号 (:) 包含在主机捕获的末尾。所以我尝试将主机更改为包含除冒号之外的任何内容:
(?<host>[^:]*)(?<=:)(?<port>\d*)
这给了我一个空主机捕获。
关于如何完成此操作的任何建议,即使冒号和端口号可选,但如果它们存在,包括端口号捕获并使冒号“消失”?
编辑:我收到的所有四个答案对我来说都很好,但要注意其中一些的 cmets。由于正则表达式结构的布局和解释很好,我接受了 sln 的回答。感谢所有回复!
【问题讨论】:
-
已编辑 - 未测试,但请尝试以下示例: (?
[^:]+)(:(? \d+))?请记住,问号本身可用于定义可选字符或整个组。 -
Jerry:我应该提到 - 这是一个更大、更复杂的正则表达式的一部分,它不仅仅做主机/端口的事情。所以我只想隔离我遇到问题的部分。
-
Zoltán:所以基本上是一个嵌套表达式?哇,这将正则表达式带到了下一个令人头疼的水平。 :) 谢谢,会试试!
-
@RuneJacobsen,是的,因为您想要一个完整的可选组(冒号后跟端口),并且想要捕获其中的数字部分,因此一个组内另一个组是有意义的。
-
不是一个真正的嵌套表达式,一个可选的捕获组应该是一个可选的集群组,特别是如果您在较大的表达式中计算命名捕获组和/或命名组最后。