Как я могу сделать так, чтобы мое регулярное выражение совпадало с первым шаблоном вместо последнего? - PullRequest
1 голос
/ 25 октября 2008

Я, наверное, все делаю неправильно. У меня есть текстовый файл, полный данных, и я хочу сопоставить и заменить шаблоны «элемент» и «номер по каталогу», которые находятся в файле. Но порядок каждого элемента в файле очень важен, поэтому я хочу сопоставить / заменить, начиная с верхней части файла, а затем перейти вниз.

Приведенный ниже фрагмент кода действительно работает, но когда я его выполняю, он заменяет третий экземпляр шаблона «SeaMonkey» и «SMKY-1978», а затем заменяет второй экземпляр этого шаблона. Я хотел бы заменить первый экземпляр шаблона, а затем второй.

Итак, я хотел бы, чтобы в выходных данных было написано «Найдены Морские Обезьяны * SMKY-1978 Курта», а затем «Найдены Морские Обезьяны SMKY-1978 Шейна», а затем оставлен Мики СМКИ-1978 Мика в одиночку, так как я хочу найти и заменить только первые 2 экземпляра шаблона. Прямо сейчас он говорит "Found SeaMonkeys SMKY-1978 Шейна" и "Found SeaMonkeys SMKY-1978 Мика", потому что он соответствует последнему шаблону каждый раз, когда выполняется цикл for.

Значит, мне не хватает едва уловимого малоизвестного символа регулярного выражения или я просто делаю то, что хочу сделать совершенно и совершенно неправильно?

Вот рабочий код:

# my regexp matches from the bottom to the top but I'd like it to replace from the top down
local $/=undef;
my $DataToParse = <DATA>;
my $item = "SeaMonkeys";
my $catNum = "SMKY-1978";
my $maxInstancesToReplace = 2;
parseData();
exit();

sub parseData {
    for (my $counter = 0; $counter < $maxInstancesToReplace; $counter++) {
        # Stick in a temporary text placeholder that I will replace later after more processing
        $DataToParse =~ s/(.+)\sELEMENT\s(.+?)\s\(Item := \"$item\".+?CatalogNumber := \"$catNum.+?END_ELEMENT(.+)/$1 ***** Found $2\'s $catNum $item. (counter: $counter) *****$3/s;
    } 
    print("Here's the result:\n$DataToParse\n");
}

__DATA__
    ELEMENT Kurt (Item := "BrightLite",
                  ItemID := 29,
                  CatalogNumber := "BTLT-9274",
                  Vendor := 100,
    END_ELEMENT

    ELEMENT Mick (Item := "PetRock",
                  ItemID := 36,
                  CatalogNumber := "PTRK-3475/A",
                  Vendor := 82,
    END_ELEMENT

    ELEMENT Kurt (Item := "SeaMonkeys",
                  ItemID := 12,
                  CatalogNumber := "SMKY-1978/E",
                  Vendor := 77,
    END_ELEMENT

    ELEMENT Joe (Item := "Pong",
                 ItemID := 24,
                 CatalogNumber := "PONG-1482",
                 Vendor := 5,
    END_ELEMENT

    ELEMENT Shane (Item := "SeaMonkeys",
                   ItemID := 1032,
                   CatalogNumber := "SMKY-1978/E",
                   Vendor := 77,
    END_ELEMENT

    ELEMENT Kurt (Item := "Battleship",
                  ItemID := 99,
                  CatalogNumber := "BTLS-5234",
                  Vendor := 529,
    END_ELEMENT

    ELEMENT Mick (Item := "SeaMonkeys",
                  ItemID := 8,
                  CatalogNumber := "SMKY-1978/F",
                  Vendor := 77,
    END_ELEMENT

    ELEMENT Frank (Item := "PetRock",
                   ItemID := 42,
                   CatalogNumber := "PTRK-3475/B",
                   Vendor := 82,
    END_ELEMENT

    ELEMENT Joe (Item := "SeaMonkeys",
                 ItemID := 8,
                 CatalogNumber := "SMKY-1979/A",
                 Vendor := 77,
    END_ELEMENT

А вот что он выводит в данный момент:

Here's the result:
        ELEMENT Kurt (Item := "BrightLite",
                      ItemID := 29,
                      CatalogNumber := "BTLT-9274",
                      Vendor := 100,
        END_ELEMENT

        ELEMENT Mick (Item := "PetRock",
                      ItemID := 36,
                      CatalogNumber := "PTRK-3475/A",
                      Vendor := 82,
        END_ELEMENT

        ELEMENT Kurt (Item := "SeaMonkeys",
                      ItemID := 12,
                      CatalogNumber := "SMKY-1978/E",
                      Vendor := 77,
        END_ELEMENT

        ELEMENT Joe (Item := "Pong",
                     ItemID := 24,
                     CatalogNumber := "PONG-1482",
                     Vendor := 5,
        END_ELEMENT

 ***** Found Shane's SMKY-1978 SeaMonkeys. (counter: 1) *****

        ELEMENT Kurt (Item := "Battleship",
                      ItemID := 99,
                      CatalogNumber := "BTLS-5234",
                      Vendor := 529,
        END_ELEMENT

 ***** Found Mick's SMKY-1978 SeaMonkeys. (counter: 0) *****

        ELEMENT Frank (Item := "PetRock",
                       ItemID := 42,
                       CatalogNumber := "PTRK-3475/B",
                       Vendor := 82,
        END_ELEMENT

        ELEMENT Joe (Item := "SeaMonkeys",
                     ItemID := 8,
                     CatalogNumber := "SMKY-1979/A",
                     Vendor := 77,
        END_ELEMENT

Ответы [ 2 ]

11 голосов
/ 25 октября 2008

. + В начале вашего регулярного выражения "жадный". Это означает, что он будет соответствовать максимальным символам.

Вы regex лучше написаны (это будет более читабельным и быстрее) как

my $re=qr/\sELEMENT\s(.+?)\s\(Item := "$item".+?CatalogNumber := "$catNum.+?END_ELEMENT/;

Я думаю, что вы можете просто повторить этот матч:

sub parseData {
    my $re=qr/\sELEMENT\s(.+?)\s\(Item := "$item".+?CatalogNumber := "$catNum.+?END_ELEMENT(.+)/;
    foreach my $counter (0..$maxInstancesToReplace) {
      # Stick in a temporary text placeholder that I will replace later after more processing
      $DataToParse =~ s/$re/ ***** Found $1\'s $catNum $item. (counter: $counter) *****$2/s;
    } 
    print("Here's the result:\n$DataToParse\n");
}

Если повторение невозможно, используйте модификатор / e regex.

0 голосов
/ 01 января 2009

Лучшим решением, по-видимому, является получение каждого раздела ELEMENT ... END_ELEMENT из данных и регулярное выражение только одного раздела за раз, а не подача всего полного набора данных в регулярное выражение за один раз. Не совсем то, что я пытался сделать, но я переписал свою программу, чтобы сделать эту частичную обработку, и она работает как шарм.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...