查找和替换文本是用VBA双引号内

问题描述 投票:0回答:2

我在寻找一种方式来查找和VBA,只有着眼于双引号内的文字,并处理所有出现替换。

我写一个SQL分析器将访问喷气SQL语句转换成T-SQL的SQL Server。其中存在挂起我正在将双引号为单引号时,单引号文本输出的一部分。

我一直在使用SQL = Replace(SQL, """", "'"),直到我碰到嵌入到字符串的一些合法的单引号,这将是该命令搞的一团糟来了。

例如,如果在Access中的SQL语句是SELECT "Kat's code is righteous"

替换()函数最终将转换这SELECT 'Kat's code is righteous'这导致在T-SQL不会喜欢一个额外的单引号。

我正在寻找将返回SELECT 'Kat''s code is righteous'所以它会在T-SQL工作的功能。

我开始寻找一个正则表达式的解决方案,然后决定它可能是太复杂了,所以我开始写通过字符串中的每个字符循环的功能。一个挑战是,最终我将使用VBA替换()函数,并没有报告有多少次作出了更换,所以之后的更换,我不知道有多少移动循环索引来搜索下一场比赛。现在我靠在椅背上正则表达式,但我不知道在VBA中如何把它每一个匹配结果中替换文本,并尽量减少其破坏字符串的机会。我试过"([^"]*)"的正则表达式,但不知道如何使它只查找包含单引号匹配。例如:https://regexr.com/483n9

我已经加载的样本SQL SELECT语句成用于测试的变量:

Public Sub Test_ReplaceInQuotes()

    Dim sTest As String

    sTest = "SELECT ""Kat's code is righteous."", left(""abc"",1), right('source code',4), ""Aaron's code has been righteous too."", ""Kat's code is righteous."", ""Right answer is '"" & Table.RightAnswer & ""'"""
    Debug.Print "Access:", sTest

    Debug.Print "Converted:", ReplaceInQuotes(sTest, "'", "''")
    'Debug.Print "Converted:", ReplaceInQuotes(sTest, "code", "source code") ' <- Make sure a longer replacement string doesn't break it.
    'Debug.Print "Converted:", ReplaceInQuotes(sTest, "right", "hid") ' <- Make sure it doesn't mess up the right() function.

    ' In another part of my parser I will replace ALL double quotes with single quotes, and & with +.
    Debug.Print "Final TSQL:", replace(ReplaceInQuotes(sTest, "'", "''"), """", "'")
End Sub

这是我希望它产生的输出:

Access:       SELECT "Kat's code is righteous.", left("abc",1), right('source code',4), "Aaron's code has been righteous too.", "Kat's code is righteous.", "Right answer is '" & Table.RightAnswer & "'"
Converted:    SELECT "Kat''s code is righteous.", left("abc",1), right('source code',4), "Aaron''s code has been righteous too.", "Kat''s code is righteous.", "Right answer is ''" & Table.RightAnswer & "''"
Final TSQL:   SELECT 'Kat''s code is righteous.', left('abc',1), right('source code',4), 'Aaron''s code has been righteous too.', 'Kat''s code is righteous.', 'Right answer is ''' & Table.RightAnswer & ''''

喷气SQL的细微差别是,它允许文字串被包裹在单引号或双引号,如In ('ab',"cd", 'efg')。 T-SQL只接受单引号的字符串。

regex vba tsql ms-access access-vba
2个回答
0
投票

请尝试这种方法。

Public Sub Test_ReplaceInQuotes()

    Dim sTest As String
    Dim Sp() As String
    Dim p As Integer, q As Integer
    Dim i As Integer

    sTest = "SELECT ""Kat's code is righteous."", left(""abc"",1), right('source code',4), ""Aaron's code has been righteous too."", ""Kat's code is righteous."", ""Right answer is '"" & Table.RightAnswer & ""'"""
'    Debug.Print "Access:", sTest
    Sp = Split(sTest, ",")

    For i = 0 To UBound(Sp)
        p = InStr(Sp(i), "('")
        If p Then
            If Right(Trim(Sp(i)), 1) = "'" Then
                Sp(i) = Left(Sp(i), p) & Chr(34) & Mid(Sp(i), p + 2)
                For q = Len(Sp(i)) To 1 Step -1
                    If Mid(Sp(i), q, 1) = "'" Then
                        Sp(i) = Left(Sp(i), q - 1) & Chr(34) & Mid(Sp(i), q + 1)
                        Exit For
                    End If
                Next q
            End If
        End If
    Next i
    Debug.Print Replace(Replace(Join(Sp, ","), "'", "''"), Chr(34), "'")
End Sub

0
投票

这是基于正则表达式的解决方案:

Option Explicit

Sub Test()

    Dim s As String
    Dim r As String
    Dim i As Long
    Dim m As Object

    s = "SELECT ""Kat's code is righteous."", left(""abc"",1), right('source code',4), ""Aaron's code has been righteous too."", ""Kat's code is righteous."", ""Right answer is '"" & Table.RightAnswer & ""'"""
    r = ""
    i = 1
    With CreateObject("VBScript.RegExp")
        .Global = True
        .Pattern = "('(?:''|[^'])*')|(""[^""]*"")"
        For Each m In .Execute(s)
            With m
                If .SubMatches(1) <> "" Then
                    r = r & Mid(s, i, .FirstIndex + 1 - i)
                    r = r & Replace(Replace(Mid(s, .FirstIndex + 1, .Length), "'", "''"), """", "'")
                Else
                    r = r & Mid(s, i, .FirstIndex + 1 + .Length - i)
                End If
                i = .FirstIndex + 1 + .Length
            End With
        Next
    End With
    If i <= Len(s) Then r = r & Mid(s, i, Len(s) - i + 1)
    Debug.Print s
    Debug.Print r

End Sub

输出如下:

SELECT "Kat's code is righteous.", left("abc",1), right('source code',4), "Aaron's code has been righteous too.", "Kat's code is righteous.", "Right answer is '" & Table.RightAnswer & "'"
SELECT 'Kat''s code is righteous.', left('abc',1), right('source code',4), 'Aaron''s code has been righteous too.', 'Kat''s code is righteous.', 'Right answer is ''' & Table.RightAnswer & ''''
© www.soinside.com 2019 - 2024. All rights reserved.