Regex 多个组而不是一个组

Regex 多个组而不是一个组,regex,vb.net,Regex,Vb.net,我正在尝试匹配URL,到目前为止它工作得很好——除了我得到了不止一个组。如果可以的话,我只想得到一组。我的目标是将地址一直增加到一个(正)斜杠 例如,给定此URL http://docs.oracle.com/javase/8/docs/technotes/guides/install/windows_jdk_install.html#BABGDJFH 产出将是: http://docs.oracle.com 另一方面,有时开头的http或https不存在;但它是可选的,我无论如何都不需要它

我正在尝试匹配URL,到目前为止它工作得很好——除了我得到了不止一个组。如果可以的话,我只想得到一组。我的目标是将地址一直增加到一个(正)斜杠

例如,给定此URL

http://docs.oracle.com/javase/8/docs/technotes/guides/install/windows_jdk_install.html#BABGDJFH
产出将是:

http://docs.oracle.com
另一方面,有时开头的
http
https
不存在;但它是可选的,我无论如何都不需要它

我正在使用的当前正则表达式

 ^(https?:\/\/)?([\da-z\.-]+)([a-z\]{2,6})([\/\w \.-]*)
第一组是可选的,这意味着URL可以以
http
https
开头,或者两者都不能。剩下的是域名本身。当我运行上面的正则表达式时,我得到了我所需要的,但不是一个组;我只想要一组。如果开头有
http
https
,则它是一个组,然后站点地址是另一个组

用于测试目的

  Dim regex As Regex = New Regex("^(https?:\/\/)?([\da-z\.-]+)([a-z\]{2,6})([\/\w \.-]*)")
  Dim m As Match = regex.Match(txtURL.Text.Trim)
  Dim lst As New List(Of String)

  Do While m.Success
      For i = 1 To 2
          Dim g As Group = m.Groups(i)
          lst.Add(g.ToString)
      Next
      Exit Do
  Loop

  ' Jump through hoops to account for one or two groups.
  If lst.Count = 1 Then
      txtConvertedURL.Text = (lst(0))
  ElseIf lst.Count = 2 Then
      txtConvertedURL.Text = (lst(0) & lst(1))
  End If

在以下组的周围加上括号:

^((https?:\/\/)?([\da-z\.-]+)([a-z\]{2,6}))([\/\w \.-]*)
您仍然会得到多个组,但第一个组将是协议和域

顺便说一下,这个正则表达式今年停止工作了。TLD不再限于6个字符。 请向给你的人抱怨

丢掉“6”,它会工作得更好

^((https?:\/\/)?([\da-z\.-]+)([a-z\]{2,}))([\/\w \.-]*)

您只需使用外部分组即可实现此目的:

Dim regex As Regex = New Regex("^((https?:\/\/)?([\da-z\.-]+)([a-z]{2,6}))([\/\w \.-]*)")
'                                ^                                       ^
Dim m As Match = regex.Match(txtURL.Text.Trim)
Dim lst As New List(Of String)

Do While m.Success
    For i = 1 To 2
        Dim g As Group = m.Groups(i)
        lst.Add(g.ToString)
    Next
    Exit Do
Loop

If lst.Count > 1 Then
    txtConvertedURL.Text = (lst(0))
End If
编辑:

@Jasen和我simul回答:他所说的仍然有多个小组,但第一个小组是你想要的全部比赛

此外,我在对Jasen答案的评论中指出的
ArgumentException
,最终归结为问题原始模式中
[a-z\]
中的反斜杠(一旦引入了额外的参数,尽管平衡)。回到问题的原始语言(“…一直到一个反斜杠。”),
[a-z\]
中的
\
没有(明显的)意义–当然与问题中的示例输入URL无关


当然,一个正斜杠而不是反斜杠表示URL中主机/域的结束;在
([\/\w\.-]*)
中,后面的
\/
说明了这一点:
[a-z\]中的反斜杠
在原始模式中似乎是错误的:我在更新的答案中删除了它,该答案为提供的样本输入生成了所需的输出。

我认为您缺少了您想要的第二个结束部分,即另一个
。目前,您显示的模式产生了一个异常:解析“^((https?:\/\/)([\da-z\.-]+)([a-z]{2,6}”)([\/\w\.-]*)”-不够)。。正如我在对答案的编辑中所指出的,我认为我们的意思是一样的。@J0e3gan不,第二个paren是在域部分之后,按照要求。我测试了这个,它不起作用。它仍然在给我整个URL,我希望从一开始到第一个“/”。尝试第二组-我不熟悉Microsoft的regex,但Posix将整个匹配放在第0个插槽中,第1组放在第1个插槽中。我也测试了它,但它不起作用,它给了我整个URL。@Codexer:查看我的最新编辑,让我知道这是否解决了问题。从我当地的测试来看,这似乎很有效,谢谢。我没有想到要把它包在一个外部组中。很晚了,我累了。再次感谢@很高兴听到这个消息。睡眠不足有时会使显而易见的事情变得不那么显而易见——不幸的是,我对这一点了如指掌顺便说一句,如果我在你的问题的原始措词中用“反斜杠”来表示“(正)斜杠”有点越界,当然可以用后续编辑来调整你的问题。我的答案中的代码适用于您以任何方式提供的示例输入(即,我展示的两个版本的regex在“反斜杠”方面都有差异)。代码非常有效。到目前为止,我已经在大约780个地址上进行了测试,它工作得很好,没有任何问题。是的,它是向前的……)