正则表达式问题:在上下文中匹配

时间:2009-09-24 09:25:09

标签: regex delphi hierarchical-data pcre dfm

我有一个带有分层文本的结构化文件,用于描述Delphi中的GUI(DFM文件)。

假设我有这个文件,我必须匹配所有“Color = xxx”行,它们在TmyButton(标记)的上下文中,但不在其他上下文中。在TMyButton-Context中,不会有更深层次的层次。

object frmMain: TfrmMain
  Left = 311
  Top = 201
  Color = clBtnFace
  object MyFirstButton: TMyButton
    Left = 555
    Top = 301
    Color = 16645072           <<<<<<MATCH THIS
    OnClick = ButtonClick
  end
  object MyLabel: TLabel
    Left = 362
    Top = 224
    Caption = 'a Caption'
    Color = 16772831
    Font.Color = clWindowText
  end
  object Panel2: TLTPanel
    Left = 348
    Top = 58
    Width = 444
    Height = 155
    Color = clRed
    object MyOtherButton: TMyButton
      Left = 555
      Top = 301
      Color = 16645072         <<<<<<MATCH THIS
      OnClick = ButtonClick
    end
  end
end

我尝试了两天,经历了许多不同的尝试。 这里有一些我不完整的模式:

/^[ ]{2,}object [A-Za-z0-9]+: TmyButton\r\n/mi  <<<Matches the needed context
/^[ ]{4,}Color = [A-Za-z0-9]+\r\n/mi            <<<Matches the needed result
/^[ ]{2,}end\r\n/mi                             <<<Matches the end of the context

(我不知道为什么,但我不得不使用“\ r \ n”而不是“$”......)。我需要将它们放在一起,但忽略除了其他“对象xxx:yyy”和“end”行之外的其他行....

我很乐意得到一些帮助!

3 个答案:

答案 0 :(得分:1)

如果我理解正确,您会尝试为此创建单个正则表达式。没有理由这样做。

  1. 只需查找带有模式object [A-Za-z0-9]+: TmyButton
  2. 的行
  3. 然后检查Color = [A-Za-z0-9]+的每一行,直到找到它或到达end关键字。
  4. 重复步骤直到文件结束
  5. 如果您尝试修改大量源文件,可以使用一些脚本来实现此目的。

答案 1 :(得分:1)

在复杂上下文中匹配一行需要一个名为lookaround的正则表达式功能,如果您想要或必须使用单个正则表达式执行此操作。具体来说,您需要PCRE不提供的可变长度后视镜。

所以有两种可能性: 使用像Rorick建议的脚本方法或使用匹配从所需上下文开始到实际匹配的所有内容的正则表达式,并使用捕获组提取它。这可以用

完成
[ ]{2,}object \w+: TMyButton\r\n.*?^([ ]{4,}Color = \w+[ \t]*\r\n)

(为清晰起见,插入空间周围的括号)。您的匹配将在捕获组\1

嵌套结构通常不适合正则表达式(更适合解析器),但如果您确定所提到的数据结构,它可能正常工作。

答案 2 :(得分:1)

我知道这不是PCRE,而是软件考古学的一个很好的替代方案。

如果从命令提示符执行此操作,您可以随时使用AWK。该脚本如下所示:

BEGIN       { inObj = 0; } // Not really necessary
/TMyButton/ { inObj = 1; }
/end$/      { inObj = 0; }
/^[ ]{4,}Color = [A-Za-z0-9]+\r\n/ && inObj == 1
            { //do whatever you need to do
              print $3;
            }

AWK可以在互联网上找到。我会尝试GAWK