VBA / VBS で正規表現による関数を使った置き換え

Pocket

JScriptのString.replaceメソッドは非常に便利だ。
置き換え文字列に、「文字列」ではなく「関数」が使えるところが意外と使える。

"test0 test1".replace(
    /\w+(\d)/g,
    function($0,$1){return (Number($1)+1).toString();})

てな具合に。

普段はWSHではVBSなんぞ使ったりしないが、
たまにどうしてもVBAやVBSを使わなくてはならない場合がある。
そんなときにそれっぽい動作をする様なのを、
不完全ながら自作してみた。

Option Explicit

Function REReplace(strSearch As String, _
             ByRef objRE As Object, _
             strFuncName As String) As String
    Dim oMatches, Match
    Dim strOut As String
    Dim nCursor As Integer
    Dim objScript
    Set objScript = CreateObject("ScriptControl")

    Set oMatches = objRE.Execute(strSearch)

    nCursor = 0
    strOut = ""
    For Each Match In oMatches
        Dim args() As String
        Dim i As Integer
        ReDim Preserve args(Match.SubMatches.Count)
        args(0) = Match.Value
        For i = 0 To Match.SubMatches.Count - 1
            args(i + 1) = Match.SubMatches(i)
        Next i

        If nCursor < Match.FirstIndex Then
            strOut = strOut & Mid(strSearch, nCursor + 1, Match.FirstIndex - nCursor)
            nCursor = Match.FirstIndex
        End If
        nCursor = nCursor + Match.Length

        ' VBSならEval使う
        strOut = strOut & CallByName(Me, strFuncName, VbMethod, args)
    Next
    REReplace = strOut
End Function

Function reptest(args) As String
    reptest = CStr(Val(args(1)) + 1)
End Function

これを適当なクラスモジュールにして使う。
標準モジュールだとCallByNameが使えないので…
ホントVBAは糞だな!!w

呼び出すときは、

Dim RE As Object
Dim RERep
Dim strRet As String

Set RE = CreateObject("VBScript.RegExp")
RE.Pattern = "\w+([\d])"
RE.ignorecase = True
RE.Global = True

' RERepという変数にクラスのインスタンスを作っておく.
Set RERep = New RegExpReplace
strRet = RERep.REReplace("test test1 test2", RE, "reptest")

のような感じで。

reptestの代わりに、必要なメソッドを追記してやって、
その名前をREReplaceメソッドに渡してやればOK。
置き換え関数を複数分ける必要がなければ、CallByName呼んでいるところを、
直接関数を呼ぶように変更してやればよろし。

コメントを残す

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください