复杂正则表达式与捕获组匹配

时间:2014-01-11 02:47:58

标签: regex vb.net

我正在尝试在天气预报中匹配某些天气(METAR格式,如果有帮助的话)。要匹配的文本可以包含以下内容:

“RA”或“SN”或“TS”后跟“B”和两个或四个数字,或“E”和两个或四个数字,或两者,或多个“B”和“E”组(例如B05E20B45),产生类似“RAB05E20B45”的东西。这意味着“雨从05点开始,在20点结束,并在45点再次开始”。另外,在同一个字符串中可以有多个这样的结构(例如“RAB05E20SNB25E55”=“从05开始下雨,在20日结束,然后在25开始下雪,在55开始结束”。)

以下是一些示例输入和我想要的输出:

RAB05                     RAB05
RAB05E15                  RAB05E15
RAB05E15SNB25             RAB05E15     SNB05
RAB05E15SNB25E55          RAB05E15     SNB25E55
TSE01RAB05E15SNB25        TSE01        RAB05E15     SNB25
TSB01E55RAE15SNB25E55     TSB01E55     RAE15        SNB25E55

我认为以下会做到这一点我很自负......

((?:RA|SN|TS)(?:(?:B|E)(?:\d{2}|\d{4}))+)+

...但是因为我在这里哭泣它显然没有。

这是我的测试代码(VB 2013):

Imports System.Text.RegularExpressions

Public Class Form1
    Dim sItem As String = "TSB05E10RAB15"
    Dim sPattern As String = "((?:RA|SN|TS)(?:(?:B|E)(?:\d{2}|\d{4}))+)+"

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        If Regex.Match(sItem, sPattern).Success Then
            Dim rxMatches As GroupCollection = Regex.Match(sItem, sPattern, RegexOptions.IgnoreCase).Groups

            '0th item is the entire match (e.g. TSB05E10RAB15)
            'Succeeding elements are capture groups
            For i = 1 To rxMatches.Count - 1
                MessageBox.Show("Match #" & i & " = " & rxMatches(i).Value)
            Next
        End If
    End Sub
End Class

我期望的结果是“TSB05E10”和“RAB15”,但我得到的只是“RAB15”。

我搜索以下内容,但无济于事:

如果有人愿意向我展示我的方式的错误......

编辑:

感谢所有帮助过的人。这是工作解决方案:

Imports System.Text.RegularExpressions

Public Class Form1
    Dim sItem As String = "TSB05E10SHRAB10E15SNB25E35B45E55"
    Dim sPattern As String = "(?:(?:SH)?(?:RA|SN)|TS)(?:(?:B|E)(?:\d{2}|\d{4}))+"
    Dim rx As New Regex(sPattern, RegexOptions.IgnoreCase)

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim matches As MatchCollection = rx.Matches(sItem)

        Label1.Text = "Input: " & sItem

        For Each match As Match In matches
            Dim groups As GroupCollection = match.Groups

            ListBox1.Items.Add(groups.Item(0).Value)
        Next
    End Sub
End Class

1 个答案:

答案 0 :(得分:0)

那些真正的METAR是?我原本以为你需要为每种降水类型设置一个开始和结束时间。另外,如果沉淀是淋浴的,则在沉淀类型之前可能存在SH。另外,您将数字量词指定为{2,4},表示2,3或4;如你所说,它确实应该是2或4。

无论如何,根据您的要求(并添加可选的SH并使用非捕获组来减少开销),请尝试:

(?:SH)?(?:RA|SN|TS)(?:(?:B|E)(?:\d{2}|\d{4}))+

修改以缩短正则表达式。

关于你的正则表达式,当你想分别解析不同的降水类型时,你的问题就是锚点,以及重复降水类型的事实

编辑:我不确定VB 2013,但在其他VB变体中,您需要将Regex对象的Global属性设置为True。


RegEx的解释:

  • (?:SH)? - 可选的非捕获组匹配“SH”
  • (?:RA|SN|TS) - 非捕获组匹配“RA”或“SN”或“TS”
  • (?:(?:B|E)(?:\d{2}|\d{4}))+ - “B”或“E”后跟2或4位数字(这可能会重复一次或多次)

非捕获组只是意味着括号中的东西被用作匹配的一部分,但该组未被“保存”以便稍后访问(这是常规括号的工作方式)。

如果你把它全部打破了,如果你花时间理解它真的很简单。