Могу ли я в Perl применить команду «grep» к данным, которые я захватил напрямую с помощью оператора триггера?

Мне нужно найти «количество» вхождений определенных слов (C7STH, C7ST2C), которые появляются в выводе команды. Команда начинается и заканчивается «фиксированным» текстом — START и END, как показано ниже. Эта команда повторяется много раз для разных узлов в файле журнала.

...

START
SLC ACL PARMG ST                   SDL                             SLI
 0  A1  17    C7STH-1&&-31         MSC19-0/RTLTB2-385
 1  A1  17    C7STH-65&&-95        MSC19-0/RTLTB2-1697

SLC ACL PARMG ST                   SDL                             SLI
 0  A2   0    C7ST2C-4             ETRC18-0/RTLTB2-417
 1  A2   0    C7ST2C-5             ETRC18-0/RTLTB2-449
 2  A2   0    C7ST2C-6             ETRC18-0/RTLTB2-961
...
END

....

Я использую оператор триггера (if (/^START$/ .. /^END$/) для получения вывода каждой команды. Теперь

  1. Есть ли способ выполнить «grep» для этих данных, не переходя построчно? Например, могу ли я получить весь текст между «START» и «END» в массив и выполнить «grep» для этого и т. Д.?

  2. Также нормально ли иметь несколько уровней блоков if с оператором триггера с точки зрения производительности?


person pkr13    schedule 02.01.2012    source источник
comment
Связанный вопрос: stackoverflow.com/q/8273383/133939   -  person Zaid    schedule 02.01.2012
comment
Зайд: Как так? Я предполагаю, что текст между «START» и «END» представляет собой произвольное количество строк.   -  person flesk    schedule 02.01.2012


Ответы (3)


Возможно, вы ищете что-то в этом роде:

#!/usr/bin/env perl
use strict;
use warnings;
my $word = q(stuff);
my @data;
while (<DATA>) {
    if ( /^START/../^END/ ) {
        chomp;
        push @data, $_ unless /^(?:START|END)/;
    }
    if ( /^END/ ) {
        my $str = "@data";
        print +(scalar grep {/$word/} (split / /,$str)),
            " occurances of '$word'\n";
        @data = ();     
    }
}
__DATA__
this is a line
START of my stuff
more my stuff
and still more stuff
and lastly, yet more stuff
END of my stuff
this is another line
START again
stuff stuff stuff stuff
yet more stuff
END again

... который выведет:

3 occurances of 'stuff'
5 occurances of 'stuff'
person JRFerguson    schedule 02.01.2012
comment
Большое спасибо за помощь и ценю вашу помощь в предоставлении даже примера кода с примером. Помещение строк в массив соответствует моей цели, так как мне нужно искать разные слова в этом массиве. Но понять некоторые из ваших стилей кодирования было сложно для новичка вроде меня :). Есть ли какая-то особая причина для использования шаблона типа (?:START|END) в регулярном выражении, а также двукратного преобразования массива в строку и последующего разделения?? - person pkr13; 02.01.2012
comment
@pkr13 : шаблон /^(?:START|END)/ соответствует либо START, либо END (чередование), если шаблон привязан к началу строки. ?: отключает захват, что было бы ненужным накладным расходом. Без круглых скобок шаблон пришлось бы писать как /^START|^END/ -- ИМХО менее читабельно. Преобразование массива в строку было выполнено для разделения. Это было разработано, чтобы позволить подсчитывать несколько совпадений с шаблоном в строке как более чем одно совпадение. - person JRFerguson; 03.01.2012

Это будет простое решение:

my $number = grep {/particular word/} grep {/START/../END/} <>;

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

grep {/START/../END/} <> создает список элементов внутри и включая разделители, а grep {/particular word/} работает с этим списком.

С точки зрения производительности вам было бы лучше с

for (<>) {
    $number++ if /START/../END/ and /a/;
}

Обратите внимание, что вы должны использовать and вместо && или заключать выражение триггера в круглые скобки из-за приоритета оператора.

Сочетание обоих:

my $number = grep {/START/../END/ and /particular word/} <>;
person flesk    schedule 02.01.2012
comment
Привет Флеск, Спасибо за немедленный ответ. Извините, что не предоставил образец журнала/кода. Я хочу подсчитать «разные» слова в данных. По этой причине я бы использовал подход, описанный Фергюсоном ниже, для построения массива и использования его для «grep» для каждого слова. - person pkr13; 02.01.2012
comment
@ pkr13: Тогда ты должен принять его ответ. Вы также можете отредактировать свой вопрос, включив соответствующий образец журнала/кода. - person flesk; 02.01.2012

Например, могу ли я получить весь текст между «START» и «END» в массив и выполнить «grep» для этого и т. Д.?

(push @ar,$_) if /START/ .. /END/;
grep {/word/ @ar};

Также нормально ли иметь несколько уровней блоков if с оператором триггера с точки зрения производительности?

Пока вы не работаете в НАСА.

person Community    schedule 02.01.2012