Perl анализирует большой вывод Expect перед записью в файл

Я создаю программу для опроса сетевого устройства каждые 48 часов и записи выходных данных пользователя Perl и модуля Expect. На данный момент я сохраняю выходной текст в текстовый файл, а затем фильтрую текстовый файл, чтобы получить необходимую информацию. Первоначально это было нормально, так как эффективность не была такой уж большой проблемой при работе с файлом размером всего в сто КБ и сохранением большей части текста в любом случае, но я нашел новую команду, которую хочу выполнить удаленно на компьютере. сетевое устройство. Эта команда выполняется полтора часа, создает текстовый файл размером около 5 МБ, и я, вероятно, буду хранить только 10 КБ информации. Использование базового файлового ввода-вывода (чтение текстового файла, запись в текстовый файл) кажется плохой идеей, и я продолжаю думать, что должен быть лучший способ.

Что показало мое исследование на данный момент: мне, вероятно, следует использовать какую-то трубу. Что-то вроде:

open($filehandle, "myCommand");
Существуют и другие решения, но они, кажется, подразумевают, что я сохраняю ВЕСЬ файл в одну переменную, когда я хотел бы сохранить и изменить только его части перед записью в файл. TIEHANDLE хорошо работает для замены слова "печать", но я не думаю, что это необходимо или сработает здесь.

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

У меня закончились вещи для Google. Если полное решение слишком сложно для задачи, мы также будем очень признательны за подсказку о том, где могут быть следующие шаги.

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


person Seanny123    schedule 06.12.2011    source источник
comment
Недостатком записи большого количества данных в каналы является то, что они обычно имеют небольшую емкость (1-128 КБ), и если вы не координируете чтение и запись в канале, вы можете столкнуться с взаимоблокировкой.   -  person mob    schedule 06.12.2011
comment
Я думаю, что я могу сохранить его до этого размера. Мне нужно анализировать вывод только по одной строке за раз, а сам вывод не так уж и быстр.   -  person Seanny123    schedule 06.12.2011
comment
Если вы используете Perl Expect для входа в систему и выполнения команд, то разве вы уже не читаете и не анализируете некоторые данные через соединение через сокет в Perl? (например, ожидание пароля: подсказка и т. д.) Это означает, что у вас уже должен быть дескриптор файла, который вы используете для этого соединения, да…?   -  person BRPocock    schedule 06.12.2011


Ответы (2)


Perl может быстро просмотреть файл размером 5 МБ, я бы не стал беспокоиться о попытке перенаправить вывод в канал, когда вы можете просто открыть файл и проанализировать его, как только ваша работа будет выполнена.

    open(INPUT, "/path/to/file.log") or die "Can't open file: $!";

    while (<INPUT>) {
    chomp;
      if (/ERROR/) {
        print "Found an error!";
      }
    }
    close(INPUT);
    exit;

Когда вы находитесь в цикле while(), вы можете использовать регулярное выражение, разделение или что угодно, чтобы найти то, что вы ищете в файле. Текущая строка хранится в $_. Вы получите одну итерацию для каждой строки вашего входного файла.

Надеюсь это поможет...

person AWT    schedule 06.12.2011
comment
В итоге сам пришел к такому выводу. Потребовалось 3 секунды, чтобы просмотреть файл размером 10 МБ. Иногда я забываю подвергать сомнению свои предположения. Фейспалм - person Seanny123; 07.12.2011
comment
Кроме того, то, что я воображал в далеком прошлом, когда текст будет копироваться и извлекаться из сетевого буфера и передаваться непосредственно в процессор перед сохранением в памяти, потребует от меня написания ассемблера и, по меньшей мере, будет немного непрактично. Сохранение простоты было определенно лучшей идеей. - person Seanny123; 26.07.2013

В зависимости от вашей версии Perl вы можете:

open(my $fh, "-|", command => @command_arguments) or die "Error: $!";
while (<$fh>) {
  # Process output of command
}
close $fh or die "Error: $!";

В более старых версиях (я думаю, 5.6 или раньше) вы можете сделать:

my $pid = open(my $fh, "-|");
die "Failed to fork: $!" unless defined $pid;
unless ($pid) {
  exec command => @command_arguments;
  die "Failed to exec command: $!";
}
while (<$fh>) {
  # same thing etc.

Я не могу сказать из вашего поста, действительно ли вам нужен Expect. Если вам просто нужно выполнить команду и зафиксировать вывод, то вышеописанное должно подойти.

person runrig    schedule 06.12.2011
comment
Я понимаю, что это моя третья попытка оставить комментарий, и мне очень жаль, если вы получили уведомление о каждой из них. Я использую expect, потому что простое открытие сеанса Telnet и выполнение команд не удовлетворит мои потребности. Мне нужно дождаться запросов пользователя/пароля и дождаться завершения других команд, содержащихся в моем сценарии. - person Seanny123; 06.12.2011