3

複雑な RegEx パターン (いくつかとnamed groupsいくつかのnumbered groupsandを含む) を解析し、それぞれについて、またはパターン テキストと共にnon-capturing groupsレポートする方法はありますか。groupnamegroupnumber

次のような RegEx パターンがあるとします。

  (?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))

この要件の目的:

複雑な正規表現パターンの大規模なデータベースがあります。これに取り組んだ以前のプログラマーは、(?#...)これらの複雑なパターンの準備中にコメント [ ] を使用せず、さらにlinebreaksそれらのパターン内に存在しませんでした。場合によっては、これらのパターンを変更する必要があり、それらのパターン内でコメントを使用する必要もあります。今では、干し草の山を針で探すようなものです。この目的で正規表現を使用することはできませんでした。そのため、この場合にはパーサーを使用する傾向がありました。

私が試したこと:

そのためGetGroupNamesに集めてみました。の のみをGetGroupNumbers抽出できましたが、対応するテキスト パターンは抽出できませんでした。Names/Numbersgroups

Non-RegEx ソリューション/ヒントを探しています。

4

2 に答える 2

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 分ほどで作成した簡単なコードです。しかし、あなたがそれを望むなら、それは始まりです。Group-Numbers のキーとして OrderedDictionary を使用します。非キャプチャ グループと関数グループも出力に含めたい場合は、その構造を変更できます。

于 2012-11-17T00:08:34.620 に答える
0

System.Text.RegularExpressions 名前空間には、Private Reflection を使用して呼び出すことができる RegexParser クラス (内部) があります。これまでに FxCopContrib プロジェクトで使用したサンプル実装があります。

活用できる可能性のある Mono プロジェクトのRegexParser 実装があります。

次に、Deveel の正規表現ライブラリがあります。

于 2012-11-18T22:51:48.950 に答える