C# 使用.net正则表达式提取主机/端口组合-端口部分可选

C# 使用.net正则表达式提取主机/端口组合-端口部分可选,c#,.net,regex,C#,.net,Regex,假设我想从如下字符串中提取主机名和端口号: stackoverflow.com:443 这很容易。我可以这样做: (?*):(?\d*) 我不担心协议方案或有效的主机名/ip地址或tcp/udp端口,这对我的请求并不重要 但是,我还需要支持一种扭曲,这超出了我对正则表达式的了解——不带端口的主机名: stackoverflow.com 我想为此使用一个正则表达式,并且我想使用命名的捕获组,这样主机组将始终以正匹配的形式存在,而端口组仅当我们有一个冒号后跟多个数字时才存在 我试着从我对它的微弱理解

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

stackoverflow.com:443

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

(?*):(?\d*)

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

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

stackoverflow.com

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

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

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

(?[^::]+)#(1),主机,必填项
(?:#群集组启动,可选
:#冒号“:”
(?\d+)#(2),端口号
)?集群组结束
编辑-如果不使用群集组,而是使用捕获组作为该群集组,则这是Dot Net在其默认配置状态下对组进行“计数”的方式-

 (?<host> [^:]+ )         #_(2), Host, required                           
 (                        # (1 start), Unnamed capture group, optional
      :                        # Colon ':'
      (?<port> \d+ )           #_(3), Port number                           
 )?                       # (1 end)
(?[^::]+)#(2),主机,必填项
(#(1开始),未命名捕获组,可选
:#冒号“:”
(?\d+)#3),端口号
)(一完)

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

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

(?<host>[^:]+)(:(?<port>\d+))?
(?[^::+)(:(?\d+)?
这使整个冒号和端口号部分成为可选组,并捕获其中的端口号。此外,我使用加号确保主机名和端口号至少包含一个字符。

您可以使用以下方法:

(?<host>[^:]+)(:(?<port>\\d+))?
(?[^::+)(:(?\\d+)?
我建议使用正则表达式代替

// 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
    • 国际化域名()
  • 可以扩展以在将来考虑模式
  • 代码简短且标准化,因此错误更少

请参阅已编辑的使用示例-未测试,但请尝试以下示例:(?[^::+)(:(?\d+)?请记住,问号本身可以用来定义可选字符或整个组。Jerry:我应该提到-这是一个更大、更复杂的regexp的一部分,它不仅仅做主机/端口的工作。所以我只想隔离我遇到问题的部分。佐尔坦:那么基本上是一个嵌套表达式?哇,这需要正则表达式表达到下一个头痛级别。:)谢谢,我会试试@RuneJacobsen,是的,因为您想要一个完整的可选组(冒号后跟端口),并且想要捕获其中的数字部分,所以一个组在另一个组中是有意义的。不是真正的嵌套表达式,一个可选的捕获组,应该是可选的群集组,特别是当您在较大的表达式中最后计算命名捕获组和/或命名组时。这将匹配“stackoverflow.com8080”,不是吗?@ZoltánTamási但是OP说
不担心协议模式或有效主机名
我认为主机名和端口之间的冒号比有效主机名和协议模式低一级:)Zoltán是对的,它会匹配这一点,但Sabuj也是对的-对于这个regexp,我想尽可能地解析它,给定可能存在格式错误的输入。在代码中的其他点的其他regexp中,我将验证并警告非法/错误的输入。这是可行的,但您是否可以解释在d前面出现两个反斜杠的原因?也就是说,我知道\d代表一个数字。一个反斜杠和两个反斜杠之间的区别似乎是返回的捕获组的数量。它用于在C#字符串中转义反斜杠。它不应该出现在这个上下文中,但是在一个普通的c#字符串中,您必须转义它,正如您所知。@user3246354,regex应该几乎总是使用逐字字符串声明,使用at符号,所以您不必担心转义反斜杠。通常,正则表达式也不够复杂。是的,这是我的错误。这个答案已经被添加到下面的“公共验证任务”中。@ AltalalMead,请考虑该解答(FAQ)。这个问题已被添加到非正则表达式中,在“普通任务>验证”下。没有考虑这一点,因为我分析的数据不一定是URI,但是当然,这样做也是有意义的。
// Use URI class for parsing only
var uri = new Uri("http://" + fullAddress);
// get host
host = uri.DnsSafeHost;
// get port
portNum = (ushort)uri.Port;