【问题标题】:Regular expression to substitute a pattern in VB script在 VB 脚本中替换模式的正则表达式
【发布时间】:2015-05-26 06:02:10
【问题描述】:

我正在尝试在 VB 脚本中编写一个正则表达式来替换一些模式。

我的字符串可能包含零个或多个以下模式 -

&USERID
&USERID
&USERID.
&USERID.
&USERID(n)
&USERID(n)
&USERID(n).
&USERID(n).
&USERID(n1, n2)
&USERID(n1, n2)
&USERID(n1, n2).
&USERID(n1, n2).

示例字符串 -

C:\temp\&USERID_&USERID._&USERID(4)_&USERID(2,2)..txt

如果 USERID=ABCDEF,则替换后的结果字符串应如下所示 -

C:\temp\ABCDEF_ABCDEF_ABCD_BC.txt

括号中的数字表示要替换的字符数。可以使用逗号分隔的数字指定范围。为了实现这一点,我写了一个正则表达式如下 -

"((&USERID\(\d+,\d+\)\.)|(&USERID\(\d+,\d+\)\.)|(&USERID\(\d+,\d+\))|(&USERID\(\d+,\d+\)))|((&USERID\(\d\)\.)|(&USERID\(\d\)\.)|(&USERID\(\d\))|(&USERID\(\d\))|(&USERID\.)|(&USERID\.))"

使用 VBScript.RegExp 我匹配模式并获得匹配的集合。遍历每个匹配对象,我根据下标替换完整的 USERID 或其中的一部分。

正则表达式工作正常。但与字符串操作函数相比,它非常慢。

上面的模式可以优化吗?

更新:

我接受了解决我的一个问题的答案。基于正则表达式,我尝试解决另一个查找和替换问题如下 -

我有以下模式

DATE
DATE(MMDDYYYY)
DATE(DDMMYYYY)
DATE(YYYYMMDD)
DATE(YYYY)
DATE(MM)
DATE(DD)
DATE(DDMONYYYY)
DATE(MON)
DATE(MONTH)
DATE(YYDDD)
DATE(YYYYDDD)

它可能有一个终止“。”最后。

Function replaceDate(matchString, label, position, sourceString)
If label = "MMDDYYYY" or label = "" then
    replaceDate = "<MMDDYYYY>"
ElseIf label = "DDMMYYYY" then 
    replaceDate = "<DDMMYYYY>"
ElseIf label = "YYYYMMDD" then 
    replaceDate = "<YYYYMMDD>"
ElseIf label = "YYYY" then 
    replaceDate = "<YYYY>"
ElseIf label = "MM" then 
    replaceDate = "<MM>"
ElseIf label = "DD" then 
    replaceDate = "<DD>"
ElseIf label = "DDMONYYYY" then 
    replaceDate = "<DDMONYYYY>"
ElseIf label = "MON" then 
    replaceDate = "<MON>"
ElseIf label = "MONTH" then 
    replaceDate = "<MONTH>"
ElseIf label = "YYDD" then 
    replaceDate = "<YYYYDDD>"
Else
    replaceDate = ""
end if  
End Function


With new RegExp
    .Global = True 
    .IgnoreCase = False
    .Pattern =  "(?:&(?:amp;)?)?DATE(?:\((MMDDYYYY|DDMMYYYY|YYYYMMDD|YYYY|MM|DD|DDMONYYYY|MON|MONTH|YYDDD|YYYYDDD)?\))?\.?"
    strTempValue = .Replace(strTempValue, GetRef("replaceDate"))
End with

【问题讨论】:

    标签: regex vbscript expression


    【解决方案1】:

    没有更多的数据很难测试,但如果性能更好,你可以试试

    Dim USERID
        USERID = "ABCDEF"
    
    Dim originalString    
        originalString = "C:\temp\&USERID_&amp;USERID._&USERID(4)_&USERID(2,2)..txt"
    
    Dim convertedString
    
        Function replaceUSERID(matchString, n1, n2, position, sourceString)
            n1 = CLng("0" & Trim(n1))
            n2 = CLng("0" & Trim(Replace(n2, ",", "")))
            If n1 < 1 Then 
                replaceUSERID = USERID
            ElseIf n2 > 0 Then 
                replaceUSERID = Mid(USERID, n1, n2)
            Else 
                replaceUSERID = Left(USERID, n1)
            End If 
        End Function 
    
        With New RegExp
            .Pattern = "(?:&(?:amp;)?)?USERID(?:\((\s*\d+\s*)(,\s*\d+\s*)?\))?\.?"
            .Global = True 
            .IgnoreCase = False
            convertedString = .Replace(originalString, GetRef("replaceUSERID"))
        End With 
    
        WScript.Echo originalString
        WScript.Echo convertedString
    

    对于多个“标签”替换

    Option Explicit
    
    Dim dicLabels
        Set dicLabels = WScript.CreateObject("Scripting.Dictionary")
    
        With dicLabels
            .Add "USERID", "ABCDEF"
            .Add "LUSER", "ABCDEF"
            .Add "ID", "GHIJKL"
        End With
    
    Dim originalString    
        originalString = "C:\temp\&USERID_&amp;USERID._&USERID(4)_&USERID(2,2)_ID(2,3)_&amp;LUSER..txt"
    
    Dim convertedString
    
        Function replaceLabels(matchString, label, n1, n2, position, sourceString)
            If Not dicLabels.Exists(label) Then 
                replaceLabels = matchString
            Else 
                n1 = CLng("0" & Trim(n1))
                n2 = CLng("0" & Trim(Replace(n2,",","")))
                replaceLabels = dicLabels.Item(label)
                If n1 > 0 Then 
                    If n2 > 0 Then 
                        replaceLabels = Mid(dicLabels.Item(label), n1, n2)
                    Else 
                        replaceLabels = Left(dicLabels.Item(label), n1)
                    End If 
                End If
            End If
        End Function 
    
        With New RegExp
            .Pattern = "(?:&(?:amp;)?)?("& Join(dicLabels.Keys, "|") &")(?:\((\s*\d+\s*)(,\s*\d+\s*)?\))?\.?"
            .Global = True 
            .IgnoreCase = False
            convertedString = .Replace(originalString, GetRef("replaceLabels"))
        End With 
    
        WScript.Echo originalString
        WScript.Echo convertedString
    

    【讨论】:

    • 谢谢!我尝试了几个输入字符串。我通过对字符串操作版本运行循环来比较性能。它工作正常。
    • 与 USERID 类似,我还有一些其他模式,如 ID、LUSER 等。为了简单起见,我避免在原始查询中提及相同的模式。我们如何使“replaceUSERID”通用?有没有办法将要替换的值作为参数传递?
    • 这很好用。此代码将驻留在库中。是否有任何优雅的方式将“dicLabels”传递给 replaceLabels 方法而不是全局范围?
    • 根据您的正则表达式,我尝试解决另一个查找和替换问题。查看更新后的帖子。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-20
    • 1970-01-01
    • 1970-01-01
    • 2012-02-12
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    相关资源
    最近更新 更多