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

本文关键字:口部 regex 主机 组合 提取 net | 更新日期: 2023-09-27 17:54:04

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

stackoverflow.com: 443

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

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

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

但是,我还需要支持一个超出正则表达式知识范围的变化——不带端口的主机名: stackoverflow.com

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

我试图从我对它的微弱理解中做一个积极的回顾:

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

这个比较接近,但是冒号(:)包含在主机捕获的末尾。所以我试着改变主机,包括除了冒号以外的任何内容,像这样:

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

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

关于如何实现这一点的任何建议,即使冒号和端口号可选,但如果它们存在,包括端口号捕获并使冒号"消失"?

编辑:我收到的所有四个答案对我来说都很好,但要注意其中一些的评论。我接受了sln的答案,因为它有很好的布局和对regexp结构的解释。感谢所有的回复!

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

我建议使用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上使用的示例

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

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

    edit -如果您不使用集群组,而是使用捕获组作为集群组,这就是Dot-Net在其默认配置状态下"计数"组的方式-

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

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

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

    试试这个:

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

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

    你可以这样做:

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