我正在尝试编写VBA Regex以从Teradata SQL文本文件中删除注释。
评论有两种类型:
1 - 两个破折号的出现,' - '表示该行的剩余部分 作为评论。
2。 / * xxx * / ' / *'之间的一切和' * /'是评论。这种评论 可以分布超过1行。
复杂性是单引号中的文字,例如' - 这些短划线用单引号表示,所以不要表示即将发表的评论。
我是Regex的新手,试图弄清楚这一点已经证明超出了我。我一直在思考否定前瞻。
有人可以帮忙吗?
这是我所拥有的:
类型1:
\ - \ - [\ S \ t] * $
类型2:
/ \ * [\ S \ S] *?\ * /
答案 0 :(得分:1)
基于递归解析器调用的算法。有几种模式:3个子类型解析,引用解析和正常的注释。正常模式可以通过任何其他模式交替,这又是唯一的正常模式。因此e。 G。在注释中引用字符,引用文本中的任何注释字符都将被忽略。要搜索的字符取决于当前模式。通过块解析源块,一旦找到目标字符,则分别切换模式,当前块完成,下一个块开始于下一个递归调用。调用堆栈存储瞬态结果。源结束后,向后进程启动,每个被调用的解析器连接并返回它的块,最后检索完整的代码。
以下是代码:
Option Explicit
Sub RemoveComments()
Dim strOriginal As String
Dim strProcessed As String
strOriginal = ReadTextFile("C:\Users\DELL\Desktop\tmp\source.sql", 0) ' -2 - System default, -1 - Unicode, 0 - ASCII
Parse strOriginal, strProcessed, 0
WriteTextFile strProcessed, "C:\Users\DELL\Desktop\tmp\result.sql", 0
End Sub
Sub Parse(strSrc As String, strRes As String, lngMode As Long)
Static objRegExp As Object
Dim strBeg As String
Dim objMatches As Object
Dim lngPos As Long
Dim lngEscPos As Long
Dim strRet As String
If objRegExp Is Nothing Then ' initialize regexp once
Set objRegExp = CreateObject("VBScript.RegExp")
With objRegExp
.Global = False
.MultiLine = True
.IgnoreCase = True
End With
End If
strRes = ""
If strSrc = "" Then Exit Sub ' source completed
strBeg = "" ' preceding chunk is empty by default
Select Case lngMode
Case 0 ' processing normal
With objRegExp
.Pattern = "(\/\*)|(^[ \t]*--)|(--)|(\')"
Set objMatches = .Execute(strSrc)
If objMatches.Count = 0 Then
strRes = strSrc
Exit Sub ' source completed
End If
lngPos = objMatches(0).FirstIndex
With objMatches(0)
Select Case True
Case .SubMatches(0) <> ""
lngMode = 1 ' start multiline comment
Case .SubMatches(1) <> ""
lngMode = 2 ' start whole line comment
Case .SubMatches(2) <> ""
lngMode = 3 ' start singleline comment
Case .SubMatches(3) <> ""
lngMode = 4 ' start text in quotes
lngPos = lngPos + 1 ' skip found quote char
End Select
End With
End With
strBeg = Left(strSrc, lngPos)
lngPos = lngPos + 1
Case 1 ' processing multiline comment
lngMode = 0 ' start normal
lngPos = InStr(strSrc, "*/")
If lngPos = 0 Then Exit Sub ' source completed, comment unclosed
lngPos = lngPos + 2 ' skip comment closing char
Case 2 ' processing whole line comment
lngMode = 0 ' start normal
lngPos = InStr(strSrc, vbCrLf)
If lngPos = 0 Then Exit Sub ' source completed
lngPos = lngPos + 2 ' skip new line char
Case 3 ' processing singleline comment
lngMode = 0 ' start normal
lngPos = InStr(strSrc, vbCrLf)
If lngPos = 0 Then Exit Sub ' source completed
Case 4 ' processing text within quotes
lngPos = InStr(strSrc, "'")
If lngPos = 0 Then Exit Sub ' source completed
If Mid(strSrc, lngPos, 2) = "''" Then ' escaped quote char ''
strBeg = Left(strSrc, lngPos + 1) ' store preceding chunk with escaped quote char
lngPos = lngPos + 2 ' shift next from escaped quote char
Else
lngMode = 0 ' start normal
strBeg = Left(strSrc, lngPos) ' store preceding chunk with quote char
lngPos = lngPos + 1 ' shift next from quote char
End If
End Select
Parse Mid(strSrc, lngPos), strRet, lngMode ' recursive parser call
strRes = strBeg & strRet ' concatenate preceding chunk with processed and return result
End Sub