Как мне читать абзацы за раз с помощью Perl?

когда я пишу

#!/usr/bin/perl -w
use strict;

while( <DATA> ) {
    print "\n-------------------------\n\n";
    print;
    <>;
}

после каждого «возврата» я получаю одну строку.

Почему я не получаю со следующим скриптом после каждого "возврата" один абзац?

#!/usr/bin/perl -w
use strict;

local $/ = "";

while( <DATA> ) {
    print "\n-------------------------\n\n";
    print;
    <>;
}

__DATA__
line one
line two
line three
line four
line five

line six
line seven
line eigth
line nine

line ten
line eleven
line twelve

person sid_com    schedule 27.11.2009    source источник


Ответы (3)


В вашем первом скрипте с переменной $/, установленной по умолчанию "\n", ‹DATA› будет возвращать только одну строку за раз.

Я считаю, что второй скрипт делает то, что вы хотите, просто ‹› не прекратит чтение при «возврате», а скорее при ‹ctrl-d› из-за вашей настройки $/ (как кто-то другой указал ‹› читает из STDIN, но я думаю, вы уже знаете это и используете его для регулирования вывода).

Если вы действительно хотите регулировать вывод с помощью «return», вам нужно сделать больше с $/ в цикле.

while( <DATA> ) {
    print "\n-------------------------\n\n";
    print;
    $/ = "\n"; # default so that the following terminates the read on 'return'
    <>;
    $/ = ""; 
}   
person shank    schedule 27.11.2009

Я думаю, вы ожидаете эту строку

local $/ = "";

изменить поведение

<DATA>

продолжать чтение до конца данных.

Но на самом деле это занимает что-то вроде этого

{
    local $/;  # $/ becomes undef in this block
    ...
}

включить режим slurp (и ограничить этот режим в область внутри {curlys}).

По сути, это говорит «забудьте о том, чтобы думать о новых строках как о маркере конца записи»,

Кроме того... в вашем коде есть тай-файтер!

while( <DATA> ) {
    print "\n-------------------------\n\n";
    print;
    <>;    # <-- Feel the power of the DARK SIDE!!!
}

Этот маленький парень будет читать из STDIN, а не из DATA — это действительно то, что вам нужно?

person Ed Guiness    schedule 27.11.2009
comment
На самом деле истребитель Perl — это ‹=›, который мы также иногда называем оператором космического корабля. - person brian d foy; 27.11.2009
comment
Я знаю, но ‹› настолько близко, что мой ухмыляющийся пятничный мозг не мог удержаться от того, чтобы не вспомнить эту маленькую деталь. - person Ed Guiness; 27.11.2009
comment
Мне кажется, нам придется изобрести оператор <-o->. - person Sinan Ünür; 27.11.2009
comment
@edg: я думаю, совершенно ясно, что чтение из STDIN является преднамеренным, но он хочет, чтобы режим абзаца был только для DATA, а не для STDIN. - person ysth; 27.11.2009

Использование ‹> таким образом (интерактивно) в режиме абзаца может привести к путанице. Он не вернется, когда вы нажмете «возврат»; вместо этого он будет читать, пока не встретит непустую строку (начало абзаца), затем будет читать, пока не встретит пустую строку (конец этого абзаца), затем продолжит чтение, пока не встретит непустую строку (начало абзаца). следующего абзаца, который будет помещен в буфер, а не возвращен), поэтому он знает, что он отбрасывает все лишние пустые строки.

Возможно, вы должны использовать:

local $/ = "\n"; <>

вместо этого в конце вашего цикла. Или, может быть, POSIX::getchar().

person ysth    schedule 27.11.2009