2012-11-16 19 views
3

有沒有什麼辦法來解析複雜的正則表達式(包含幾個named groups以及一些numbered groupsnon-capturing groups)和大約每groupname或圖案文字一起groupnumber報告。解析一個正則表達式模式

想,我有這樣的正則表達式:

(?im)(?<x>\b[a-s03]+\b)(?-i)(?<a>\p{L}+?,(?<b>.+?:(?<c>.+?;(?<d>.+?(?:\d|sample-text|(\k'x'|sos30)))))) 

而且我喜歡解壓:=

Named groups: 
    x==>(?<x>\b[a-s03]+\b) 
    a==>(?<a>\p{L}+?,(?<b>.+?:(?<c>.+?;(?<d>.+?(?:\d|sample-text|(\k'x'|sos30)))))) 
    b==>(?<b>.+?:(?<c>.+?;(?<d>.+?(?:\d|sample-text|(\k'x'|sos30))))) 
    c==>(?<c>.+?;(?<d>.+?(?:\d|sample-text|(\k'x'|sos30)))) 
    d==>(?<d>.+?(?:\d|sample-text|(\k'x'|sos30))) 

    Numbered groups: 
    1==>(\k'x'|sos30) 

    Non-capturing-groups: 
    1st==>(?:\d|sample-text|(\k'x'|sos30)) 

目的本要求:

我有一個複雜RegEx模式的大型數據庫。之前編寫的程序在編寫這些複雜模式時沒有使用任何註釋[(?#...)],而且在這些模式中不存在linebreaks。我必須在某些情況下修改這些模式,並且必須在這些模式中使用註釋。現在它就像是在乾草堆裏尋找針。我完全無法爲此使用RegEx。所以,我傾向於在這種情況下使用解析器。

我的嘗試:

我試圖GetGroupNamesGetGroupNumbers收集用於這一目的。我只能提取groupsNames/Numbers,但不能提取相應的文本模式。

我正在尋找非RegEx解決方案/一些提示。

+0

我不知道任何現有解析正則表達式的解決方案。儘管如果你只是簡單地循環一遍,那麼自己製作類似的東西可能不是非常困難,但要捕捉左括號並尋找相應的右括號。基於文本模式,你可以看到它是什麼類型的組。 – Patrickdev

+0

@Patrickdev:謝謝你,給你的時間評論。實際上,我描述的例子是一個非常簡單的例子,根本沒有「括號」,因爲實際模式更加複雜(主要是嵌套結構和大量括號)。但是,是的,我同意你的建議,準備一個新的Parser。但是,這將會像重新發明輪子一樣。當然,如果沒有其他解決方案,我會考慮它。 – Cylian

+0

看看http://www.regex101.com - 這裏可能有幫助。 –

回答

3

這個怎麼樣,對於這個:

(?im)(?<x>\b[a-s03]+\b)(?-i)(?<a>\p{L}+?,(?<b>.+?:(?'c'.+?;(.+?(?:\d|sample-text|(\k'x'|sos30)))))) 

此,作爲輸出:

(0)<0>:  (?im)(?<x>\b[a-s03]+\b)(?-i)(?<a>\p{L}+?,(?<b>.+?:(?'c'.+?;(.+?(?:\d|sample-text|(\k'x'|sos30)))))) 
(1)<x>:  \b[a-s03]+\b 
(2)<a>:  \p{L}+?,(?<b>.+?:(?'c'.+?;(.+?(?:\d|sample-text|(\k'x'|sos30)))) 
(3)<b>:  .+?:(?'c'.+?;(.+?(?:\d|sample-text|(\k'x'|sos30))) 
(4)<c>:  .+?;(.+?(?:\d|sample-text|(\k'x'|sos30)) 
(5)<5>:  .+?(?:\d|sample-text|(\k'x'|sos30) 
(6)<6>:  \k'x'|sos30 

這是代碼:

Imports System.Collections.Specialized 
Module Module1 
Public DictGroups As New OrderedDictionary 
Public DictTrackers As New Dictionary(Of Integer, Boolean) 
Public intGroups As Integer = 0 
Public CommandGroup As Boolean = False 
Sub Main() 
    Dim regexToEval As String = "(?im)(?<x>\b[a-s03]+\b)(?-i)(?<a>\p{L}+?,(?<b>.+?:(?'c'.+?;(.+?(?:\d|sample-text|(\k'x'|sos30))))))" 
    Dim curChar As String = "" 
    DictGroups.Add(0, "(0)<0>: " & vbTab) 
    DictTrackers.Add(0, True) 
    For i = 1 To regexToEval.Length 
     Dim iChar As String = regexToEval.Substring(i - 1, 1) 
     If curChar <> "\" AndAlso iChar = ")" Then EndGroup() 
     AddStrToTrackers(iChar) 
     If curChar = "\" OrElse iChar <> "(" OrElse regexToEval.Length < i + 2 Then curChar = iChar : Continue For 
     If regexToEval.Substring(i, 1) = "?" Then 
      i += 1 : AddStrToTrackers("?") 
      If regexToEval.Substring(i, 1) = ":" Then i += 1 : AddStrToTrackers(":") : curChar = ":" : Continue For 
      Dim NameLength As Integer = 0 
      If regexToEval.Substring(i, 1) = "<" Or regexToEval.Substring(i, 1) = "'" Then 
       i += 1 : AddStrToTrackers(regexToEval.Substring(i - 1, 1)) 
       i += 1 
       For x = i To regexToEval.Length 
        If regexToEval.Substring(x - 1, 1) = ">" Or regexToEval.Substring(x - 1, 1) = "'" Then 
         NameLength = x - i 
         Exit For 
        End If 
       Next 
      Else 
       CommandGroup = True 
       Continue For 
      End If 
      If NameLength > 0 Then 
       Dim GroupName As String = regexToEval.Substring(i - 1, NameLength) 
       i += NameLength : curChar = regexToEval.Substring(i - 1, 1) : AddStrToTrackers(GroupName & curChar) 
       intGroups += 1 
       DictGroups.Add(intGroups, "(" & DictGroups.Count & ")<" & GroupName & ">: " & vbTab) 
       DictTrackers.Add(intGroups, True) 
       Continue For 
      End If 
     End If 
     curChar = iChar 
     intGroups += 1 
     DictGroups.Add(intGroups, "(" & DictGroups.Count & ")<" & intGroups.ToString & ">: " & vbTab) 
     DictTrackers.Add(intGroups, True) 
    Next 
    Dim Output As String = MakeOutput() 
End Sub 

Private Function MakeOutput() As String 
    Dim retString As String = String.Empty 
    For i = 0 To DictGroups.Count - 1 
     retString &= DictGroups(i) & vbCrLf 
    Next 
    Return retString 
End Function 

Public Sub EndGroup() 
    If CommandGroup Then 
     CommandGroup = False 
     Exit Sub 
    End If 
    Dim HighestNum As Integer = 0 
    For Each item In DictTrackers 
     If Not item.Value Then Continue For 
     If item.Key > HighestNum Then HighestNum = item.Key 
    Next 
    If HighestNum <> 0 Then DictTrackers(HighestNum) = False 
End Sub 

Public Sub AddStrToTrackers(ByVal addString As String) 
    For Each item In DictTrackers 
     If item.Value Then DictGroups(item.Key) &= addString 
    Next 
End Sub 
End Module 

唯一的區別是,我沒有捕獲非捕獲組和功能組。當然,這只是我在10分鐘內製作的快速代碼。但如果你想要的話,這是一個開始。我使用OrderedDictionary作爲Group-Numbers的鍵。如果您想在輸出中包含非捕獲組和功能組,您可以更改該結構。

+0

非常感謝。我基本上在尋找一些內置的'.NET'庫。需要一些修改,但你的代碼在這方面工作正常。 – Cylian

0

System.Text.RegularExpressions名稱空間中有一個RegexParser類(內部),您可以使用Private Reflection調用該類。我有一個sample implementation到目前爲止我在我的FxCopContrib項目中使用。

有你可能能夠利用的RegexParser implementation from the Mono project

然後是Deveel's Regex library

+0

來自OP的問題:'我正在尋找非RegEx解決方案' – Neolisk

+0

這些是非正則表達式解決方案。建議是使用平臺使用的解析器來解析正則表達式,併爲您提供組成表達式的所有元素的對象圖。這似乎正是OP正在尋找的東西。 – jessehouwing