2009-09-24 3 views
1

У меня есть структурированный файл с иерархическим текстом, который описывает графический интерфейс в Delphi (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 

(я не знаю, почему, но я должен был использовать «\ г \ п» вместо «$» ...). Мне нужно собрать это вместе, но игнорируя другие строки, кроме других строк «object xxx: yyy» и «end» ....

Я был бы рад помочь!

ответ

1

Соответствие строки в сложном контексте требует функции регулярного выражения, называемой lookaround, если вы хотите или должны сделать это с помощью одного регулярного выражения. В частности, вам понадобится переменная длина lookbehind, которую PCRE не предлагает.

Таким образом, существует две возможности: Используйте подход сценариев, например, предложенный Рориком, или используйте регулярное выражение, которое соответствует всему, от начала вашего необходимого контекста до фактического совпадения, и извлекайте его с помощью группы захвата. Это можно сделать с помощью

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

(скобки вокруг вставленного пространства для ясности). Ваша совпадение будет тогда в группе захвата \1

Вложенные структуры обычно не подходят для регулярных выражений (лучше для парсеров), но если вы уверены в структуре своих данных, как вы упомянули, это может сработать нормально.

+0

переменная длина lookbehind: thats, что я пробовал кулак ... Я думаю, что мне нужно сделать некоторые скрипты. Теперь я буду искать сначала для контекста, используя/^ [] {2,} объект \ w +: TMyButton \ r \ n (^ [] {4,}. + \ R \ n) +^[] {2} конец \ r \ n/mi, а затем в этом совпадении найдите/^ [] {4,} Цвет = \ w + \ r \ n/mi –

1

Если вы правильно поняли, вы пытаетесь создать для него одно регулярное выражение. Для этого нет оснований.

  1. Просто найти строку с рисунком object [A-Za-z0-9]+: TmyButton
  2. Затем проверьте каждую следующую строку против Color = [A-Za-z0-9]+, пока вы не найдете его или достичь end ключевого слова.
  3. Повторите шаги до конца файла

Если вы пытаетесь изменить основную часть исходных файлов, вы можете использовать некоторые сценарии для этой цели.

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.