Проблема с регулярным выражением:Совпадение в контексте

StackOverflow https://stackoverflow.com/questions/1470621

Вопрос

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

(Я не знаю почему, но мне пришлось использовать " \ n" вместо "$" ...).Мне нужно собрать это воедино, но игнорируя другие строки, кроме other "object xxx:гггг" и строки "конец"....

Я был бы рад получить некоторую помощь!

Это было полезно?

Решение

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

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

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

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

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

Другие советы

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

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

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

Я знаю, что это не 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 можно найти по всему Интернету.Я бы попробовал ПОГЛАЗЕТЬ.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top