VBS正则表达式提取多个块

时间:2015-04-19 12:01:16

标签: regex vbscript

我想使用正则表达式提取多个文本块。我的正则表达式得到了正确的开始,但也将所有内容返回到文件的末尾。

我正在使用:

re.ignorecase = true
re.multiline = false
re.global = true
re.pattern = "\balias\s=\sX[\s\S]{1,}end"

文件格式的一个例子是:

Metadata Begin
    Easting Begin
        alias = X
        projection = "geodetic"
        datum = "GDA94"
    Easting End
    Northing Begin
        alias = Y
        projection = "geodetic"
        datum = "GDA94"
    Northing End
Metadata End

我希望每次出现时从alias开始提取到下一个End的文本,这样我就可以一次处理一个别名的详细信息。 e.g。

    alias = X
    projection = "geodetic"
    datum = "GDA94"
Easting End

但是这不会在End之后获得第一个alias。相反,[\s\S]匹配在第一个alias之后到文件末尾的所有内容。但[\s\S]是我能想到的唯一一个在每一行结束时越过CrLf的技巧。

是否存在与多行第一个End匹配的正则表达式?

2 个答案:

答案 0 :(得分:3)

你需要一个非贪婪的正则表达式。 [\s\S]{1,}贪婪,尽可能匹配所有角色。要在找到匹配匹配项后停止此模式,您需要在?旁边添加非贪婪量词{1,}。所以它就像[\s\S]{1,}?。这甚至可以用更简单的形式写成[\s\S]+?

re.pattern = "\balias\s=\sX[\s\S]+?end"

如有必要,请在字符\b之前和之后添加end

DEMO

答案 1 :(得分:1)

我建议采用多步骤方法。

  1. 单挑街区:

    (Easting|Northing) Begin([\s\S]*?)\1 End
    
  2. 逐行处理其内容

    (\S+)\s+=\s+("?)(.*)\2
    
  3. 所以,当放在一起时,我们得到

    Option Explicit
    
    Dim reBlock, reLine, input
    Dim blockType, blockBody, name, value
    
    Set reBlock = New RegExp
    Set reLine = New RegExp
    
    input = LoadYourFile()
    
    reBlock.Pattern = "(Easting|Northing) Begin([\s\S]*?)\1 End"
    reBlock.Global = True
    reBlock.IgnoreCase = True
    
    reLine.Pattern = "(\S+)\s+=\s+(""?)(.*)\2"
    reLine.Global = True
    reLine.IgnoreCase = True
    
    For Each block In reBlock.Execute(input)
        blockType = block.SubMatches(0)
        blockBody = block.SubMatches(1)
        For Each line In reLine.Execute(blockBody)
            name = line.SubMatches(0)
            value = line.SubMatches(2)
            WScript.Echo blockType & ": " & name & " = " & value
        Next
    Next
    

    显着特征

    • 非贪婪匹配,如@ AvinashRaj的回答中所述。
    • 在正则表达式
    • 中反向引用
    • 结构化方法允许轻松输出上下文信息(即“这个值属于哪个块?”)