Perl readline проблема - PullRequest
       2

Perl readline проблема

1 голос
/ 08 ноября 2010

Я бы прочитал файл, например test.test, который содержит

 #test:testdescription\n
 #cmd:binary\n
 #return:0\n
 #stdin:|\n
 echo"toto"\n
 echo"tata"\n
 #stdout:|\n
 toto\n
 tata\n
 #stderr:\n

Мне удалось принять, которые после #test:; #cmd: и т. д ... но для stdin или stdout я хочу взять всю строку до следующей # в таблицу @stdin и @stdout.

Я делаю цикл while ($line = <TEST>), поэтому он будет смотреть на каждую строку. Если я вижу шаблон /^#stdin:|/, я хочу перейти к следующей строке и перенести это значение в стол, пока я не увижу следующий #.

Как перейти к следующей строке в цикле while?

Ответы [ 2 ]

2 голосов
/ 09 ноября 2010

Этот формат файла может быть легко обработан с некоторым творческим подходом при выборе подходящего значения для $/:

use strict; use warnings;

my %parsed;

{
    local $/ = '#';
    while ( my $line = <DATA> ) {
        chomp $line;
        my $content = (split /:/, $line, 2)[1];
        next unless defined $content;
        $content =~ s/\n+\z//;
        if ( my ($chan) = $line =~ /^(std(?:err|in|out))/ ) {
            $content =~ s/^\|\n//;
            $parsed{$chan} = [ split /\n/, $content];
        }
        elsif ( my ($var) = $line =~ /^(cmd|return|test)/ ) {
            $parsed{ $var } = $content;
        }
    }
}

use YAML;
print Dump \%parsed;

__DATA__
#test:testdescription
#cmd:binary
#return:0
#stdin:|
echo"toto"
echo"tata"
#stdout:|
toto
tata
#stderr:

Вывод:

---
cmd: binary
return: 0
stderr: []
stdin:
  - echo"toto"
  - echo"tata"
stdout:
  - toto
  - tata
test: testdescription
1 голос
/ 08 ноября 2010

ОБНОВЛЕНО в соответствии с заданиями пользователя

Если я правильно понял вопрос, вы хотите прочитать еще одну строку в цикле?

Если это так, вы можете:

  1. просто прочитайте еще одну строку внутри цикла.

    my $another_line = <TEST>;
    
  2. Сохраните некоторый флаг состояния и используйте его на следующей итерации цикла и накапливайте строки между stdins в буфере:

    my $last_line_was_stdin = 0;
    my @line_buffer = ();
    while ($line = <TEST>) {
        if (/^#stdin:|/) {
            #
            # Some Code to process all lines acccumulated since last "stdin"
            #
            @line_buffer = ();
            $last_line_was_stdin = 1;
            next;
        }
        push @line_buffer, $line;
    }
    

    Это решение может не выполнять 100% того, что вам нужно, но оно определяет шаблон, которому вы должны следовать в своей реализации конечного автомата: прочитать строку. Проверьте ваше текущее состояние (если это имеет значение). Основываясь на текущем состоянии и шаблоне в строке, проверьте, что делать с текущей строкой (добавить в буфер? Изменить состояние? При изменении состояния обработать буфер на основе последнего состояния?)

Кроме того, согласно вашему комментарию, у вас есть ошибка в регулярном выражении - труба (| символ) означает «ИЛИ» в регулярном выражении, поэтому вы говорите «если строка начинается с #stdin ИЛИ соответствует пустому регулярному выражению "- последняя часть всегда верна, поэтому ваше регулярное выражение будет соответствовать 100% времени. Вам нужно уйти от "|" через /^#stdin:\|/ или /^#stdin:[|]/

...