проблемы для фрагмента кода для обработки входного файла - PullRequest
1 голос
/ 27 декабря 2011

Я изучаю программу на Perl, которая включает следующий сегмент для обработки входного файла.Я не понимаю, для чего используется s/^\s+//;?Кроме того, что такое '|'и '||'стоять в open(FILE, "cat $fileName |") || die "could not open file";

open(FILE, "cat $fileName |") || die "could not open file";
while (<FILE>)
{
    s/^\s+//;
    my @line = split;
    if ($line[0]!~ /\:/) {$mark=0}
    my $var = $line[$mark];
       ## some other code
}

Ответы [ 3 ]

2 голосов
/ 27 декабря 2011

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

Оператор || в open... || die ... имеет высокий приоритет или . Если open терпит неудачу, die выполняется.

open(FILE, "cat $fileName |") - это пустая трата внешнего процесса. Чтобы прочитать файл для ввода, просто выполните:

open FILE, '<', $filename or die qq{Could not open "$filename" for reading: $!};

Скобки для вызова open являются необязательными, потому что or не связывает сильно.

Также лучше использовать лексические дескрипторы файлов:

open my $fh, '<' $filename or die qq{Could not open "$filename" for reading: $!};

Этот дескриптор файла назначается лексической переменной, которая находится только в пределах области, в которой она объявлена. Как только поток программы выходит из этой области, файл автоматически закрывается.

2 голосов
/ 27 декабря 2011

Документацию по различным функциям можно прочитать в perlfunc .

Этот код откроет файл для чтения, довольно осторожным способом передачи из cat вместо простого открытия файла. | означает, что команда оболочки cat передана в команду open, и наш дескриптор файла будет читать из вывода.

|| это просто или. Откройте канал, и если это не удастся, программа умрет.

while(<FILE>) прочитает каждую строку ввода и присвоит каждой строке $_. Эта строка затем используется неявно в подстановке и разбивается ниже. То есть s/^\s+// равно $_ =~ s/^\s+//, а split равно split(' ', $_).

s/^\s+//

Удалит ведущие пробелы. Разделение будет разбивать каждую строку на пустом месте, а элементы сохраняются в массиве @line.

Из-за использования неявного разделения на пустое пространство удаление начальных пустых мест с помощью s/^\s+// на самом деле не требуется, поскольку это делается автоматически.

Если первый элемент не содержит двоеточия :, $mark устанавливается в 0. В противном случае оно не устанавливается и, вероятно, будет использовать значение из предыдущей итерации, поскольку оно не определено внутри цикла , Наконец, $var инициализируется как номер элемента $mark, который равен либо 0, либо как угодно.

ETA: как довольно коварный упс: если $mark не определено, то есть не содержит двоеточия, тогда $var все равно будет присвоено $line[0], поскольку undef будет преобразовано в 0, с предупреждением. Если use warnings не действует, эта ошибка является бесшумной и поэтому коварной.

Кажется, этот код написан кем-то, кто не слишком много знает о Perl, и его использование может быть не очень безопасным.

0 голосов
/ 28 декабря 2011

Часть путаницы заключается в том, что разработчик использует переменную по умолчанию, $_. Многие команды Perl (я бы сказал, около 1/3 из них) действуют на $_, когда вы не указываете имя переменной в функции. Например, они синтаксически одинаковы:

my $uppercase_name = uc($_);
my $uppercase_name = uc;

В обоих случаях функция uc напечатает строку в переменной $_ заглавными буквами. Фактически, даже оператор print использует переменную $_. Опять же, они оба одинаковы:

print $_;
print;

Не одобряется использование переменной по умолчанию в новых сценариях Perl, поскольку она не добавляет ясности программе и не ускоряет ее выполнение. Я переписал тот же фрагмент кода, который вы использовали, чтобы показать отсутствующую переменную $_. Это может облегчить понимание кода:

open(FILE, "cat $fileName |") || die "could not open file";
while ($_ = <FILE>)
{
    $_ =~ s/^\s+//;
    my @line = split $_;
    if ($line[0] !~ /\:/) {
        $mark = 0;
    }
    my $var = $line[$mark];
       ## some other code
}

Обратите внимание, что оператор while помещает значение прочитанной строки в переменную $_ и что команда substitute (s/^\s+//) также работает с переменной $_ , Я надеюсь, что это немного прояснит код.

Теперь на ваши вопросы:

_ [W], что делать '|' и '||' стоять за?

|| означает или , как в том или ином . На практике или можно рассматривать как оператор if:

if (not open(FILE, "cat $fileName |")) {
   die "could not open file";
}

То есть, если оператор open не удался, выполните оператор die. Если оператору open удалось открыть файл, не выполняйте оператор die.

В Perl теперь вы видите or вместо || в таких случаях:

open(FILE, "cat $fileName |") or die "could not open file";

, что делает значение немного более очевидным: Откройте файл или убейте программу.

Один канал (|) в конце имени файла означает выполнение команды в операторе открытия (cat $filename) и чтение из вывода этой команды. Представьте себе что-то вроде этого:

open (COMMAND, "java -jar foo.war|") or die "Can't execute 'java -jar foo.war'";

Теперь я запускаю команду java -jar foo.war и использую ее вывод в моем скрипте Perl.

Вы можете сделать это и наоборот:

open (MAIL, "|mail $recipient") or die "Can't mail $recipient";
print MAIL "Dear $recipient\n\n";
print MAIL "I hope everything is well.\n";
print MAIL "Sincerely,\n\nDavid";
close MAIL;

Я сейчас открываю команду mail $recipient и пишу ей с помощью print операторов. В этом случае я пишу $recipient с простым сообщением.

Я не понимаю, что такое s / ^ \ s + //; используется для?

В оригинальной программе это было на одной строке:

s/^\s+//;

Я добавил отсутствующую переменную , которая должна немного прояснить это:

 $_ =~ s/^\s+//;

Это команда замены в Perl. Он принимает переменную $_ и заменяет регулярное выражение ^\s+ ничем. Если вы не понимаете, что такое регулярные выражения, вам следует взглянуть на Perldoc tutorial на эту тему. В основном это удаление всех пробелов, табуляций и других форм пробела из начала строки.

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