使用.net regex提取主机/端口组合 – 端口部分可选

假设我想从字符串中提取主机名和端口号,如下所示:

stackoverflow.com:443

这很容易。 我可以这样做:

(?.*):(?\d*)

我不担心协议方案或有效的主机名/ IP地址或tcp / udp端口,这对我的请求并不重要。

但是,我还需要支持一种扭曲,这超出了我对正则表达式的了解 – 没有端口的主机名:

stackoverflow.com

我想为此使用单个正则表达式,并且我想使用命名捕获组,以便主机组始终以正匹配存在,而当且仅当我们有一个冒号后跟一些数字时,端口组才存在数字。

我试图通过对它的微弱理解做出积极的观察:

(?.*)(?<=:)(?\d*)

这很接近,但冒号(:)包含在主机捕获结束时。 所以我试图改变主机,除了像这样的冒号:

(?[^:]*)(?<=:)(?\d*)

这给了我一个空主机捕获。

有关如何实现此目的的任何建议,即使冒号和端口号可选,但如果它们在那里,包括端口号捕获并使冒号“消失”?

编辑:我收到的所有四个答案都适合我,但请注意其中一些答案。 由于regexp结构的良好布局和解释,我接受了sln的答案。 感谢所有回复!

这可能是(?[^:]+)(?::(?\d+))?

  (? [^:]+ ) # (1), Host, required (?: # Cluster group start, optional : # Colon ':' (? \d+ ) # (2), Port number )? # Cluster group end 

编辑 – 如果您不使用群集组,并使用捕获组作为该群集组,则这就是Dot-Net在其默认配置状态下“计算”组的方式 –

  (? [^:]+ ) #_(2), Host, required ( # (1 start), Unnamed capture group, optional : # Colon ':' (? \d+ ) #_(3), Port number )? # (1 end) 

我建议使用Uri类而不是正则表达式。

 // Use URI class for parsing only var uri = new Uri("http://" + fullAddress); // get host host = uri.DnsSafeHost; // get port portNum = (ushort)uri.Port; 

好处是

  • 它支持:
    • IPv4和IPv6
    • 国际化域名( IDN )
  • 可以扩展到将来考虑架构
  • 代码短而标准化,错误少

请参阅.NET Fiddle上使用的示例

如果你的主机名不包含:像ipv64那么试试这个:

 (?[^:]*):?(?\d*) 

试试这个:

 (?[^:]+)(:(?\d+))? 

这使得整个冒号和端口号部分成为可选组,并捕获其中的端口号。 此外,我使用加号来确保主机名和端口号至少包含一个字符。

你可以用这个:

 (?[^:]+)(:(?\\d+))?