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

时间:2014-03-27 19:34:06

标签: c# .net regex

说我想从这样的字符串中提取主机名和端口号:

stackoverflow.com:443

这很简单。我可以这样做:

(?<host>.*):(?<port>\d*)

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

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

stackoverflow.com

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

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

(?<host>.*)(?<=:)(?<port>\d*)

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

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

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

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

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

5 个答案:

答案 0 :(得分:4)

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

// 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

上的使用示例

答案 1 :(得分:2)

这可能是(?<host>[^:]+)(?::(?<port>\d+))?

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

编辑 - 如果您不使用群集组,并使用捕获组作为该群集组,则这就是Dot-Net&#34;计数&#34;处于默认配置状态的组 -

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

答案 2 :(得分:1)

如果您的主机名不包含:,例如ipv64,请尝试以下方法:

(?<host>[^:]*):?(?<port>\d*)

答案 3 :(得分:1)

试试这个:

(?<host>[^:]+)(:(?<port>\d+))?

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

答案 4 :(得分:1)

您可以使用:

(?<host>[^:]+)(:(?<port>\\d+))?