[英]Parse a RegEx pattern
有没有什么办法来解析复杂的正则表达式(包含几个named groups
以及若干numbered groups
和non-capturing groups
),并报告有关每个groupname
或groupnumber
与模式文本一起。
假设,我确实有一个这样的 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))
本要求的目的:
我确实有一个包含复杂 RegEx 模式的大型数据库。 以前的程序在准备这些复杂的模式时没有使用任何注释 [ (?#...)
],而且这些模式中不存在linebreaks
。 在某些情况下,我必须修改这些模式,并且还必须在这些模式中使用注释。 现在就像大海捞针一样。 为此,我根本无法使用 RegEx。 所以,我倾向于在这种情况下使用解析器。
我试过的:
为此,我尝试了GetGroupNames
和GetGroupNumbers
集合。 我只能提取groups
的Names/Numbers
,而不能提取相应的文本模式。
我正在寻找非正则表达式解决方案/一些提示。
这个怎么样,为此:
(?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 作为组号的键。 如果您还想在输出中包含非捕获组和功能组,则可以更改该结构。
System.Text.RegularExpressions 命名空间中有一个 RegexParser 类(内部),您可以使用私有反射调用它。 到目前为止,我在 FxCopContrib 项目中使用了一个示例实现。
您可以利用Mono 项目中的RegexParser 实现。
然后是Deveel 的 Regex 库。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.