2010-05-06 2 views
2

У меня в основном следующий Perl я работаю с:Perl разделить на пустой файл

open I,$coupon_file or die "Error: File $coupon_file will not Open: $! \n"; 
while (<I>) { 
$lctr++; 
chomp; 
my @line = split/,/; 
if ([email protected]) { 
    print E "Error: $coupon_file is empty!\n\n"; 
    $processFile = 0; last; 
} 
} 

У меня возникли проблемы определения того, что раскол /,/функция возвращается, если пустой файл передается на него , Блок кода if (! @line) никогда не выполняется. Если я изменю это значение, то будет

if (@line) 

, чем выполняется блок кода. Я прочитал информацию о функции разделения perl по адресу http://perldoc.perl.org/functions/split.html и обсуждении here о тестировании пустого массива, но не уверен, что здесь происходит.

Я новичок в Perl, поэтому, вероятно, отсутствует что-то прямое здесь.

ответ

1

Ниже приведены несколько советов, чтобы сделать ваш код более идиоматических:

  • special variable $. уже содержит номер текущей строки, так что вы можете скорее избавиться от $lctr.
  • Действительно ли пустые строки действительно ошибки, или вы можете их игнорировать?
  • Выдвиньте список, возвращенный с split, и дайте названия произведений.
  • Пусть Perl сделать отверстие с "diamond operator":

Нулевая указатель_на_файл <> является особенным: он может быть использован для имитации поведения sed и awk. Вход от <> поступает либо из стандартного ввода, либо из каждого файла, указанного в командной строке. Вот как это работает: в первый раз оценивается <>, проверяется массив @ARGV, и если он пуст, $ARGV[0] установлен в "-", который при открытии дает вам стандартный ввод. Затем массив @ARGV обрабатывается как список имен файлов. Петля

while (<>) { 
... # code for each line 
} 

эквивалентен следующий Perl-подобный псевдокод:

unshift(@ARGV, '-') unless @ARGV; 
while ($ARGV = shift) { 
    open(ARGV, $ARGV); 
    while (<ARGV>) { 
    ... # code for each line 
    } 
} 

за исключением того, что это не так громоздко, чтобы сказать, и будет реально работать.

Скажите ваш вклад в файле с именем input и содержит

Campbell's soup,0.50 
Mac & Cheese,0.25

Затем с

#! /usr/bin/perl 

use warnings; 
use strict; 

die "Usage: $0 coupon-file\n" unless @ARGV == 1; 

while (<>) { 
    chomp; 

    my($product,$discount) = split /,/; 
    next unless defined $product && defined $discount; 

    print "$product => $discount\n"; 
} 

, что мы бежим, как показано ниже на Unix:

$ ./coupons input 
Campbell's soup => 0.50 
Mac & Cheese => 0.25
0

Пустой файл или пустая строка? Независимо от того, попробуйте этот тест вместо [email protected].

if (scalar(@line) == 0) { 
    ... 
} 

Метод scalar возвращает длину массива в perl.

Некоторые уточнения:

if (@line) { 
} 

То же самое, как:

if (scalar(@line)) { 
} 

В скалярном контексте, массивы (@line) возвращает длину массива. Итак, scalar(@line) заставляет @line оценивать в скалярном контексте и возвращает длину массива.

+0

Таким образом, используя только if (@line) проверяет, что массив определен или существует, и NOT th e размер массива? – Casey

+0

его perl используя контекст, чтобы определить, что он собирается делать. 'if (@line)' совпадает с 'if (scalar (@line))', но с '' @ line', вы не гарантируете, что его оценивают в контексте «скалярного». – dlamotte

+0

№ 'if (@line)' то же самое, что и 'if (scalar (@line))', который оценивается как true, когда в списке есть элементы. – jamessan

5
  1. Если файл пуст, тело цикла while не будет работать вообще.
  2. Оценка массива в скалярном контексте возвращает количество элементов в массиве.

    split /,/ всегда возвращает список элементов 1+, если определено $_.

0

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

Если строка, пожалуйста, исправьте текст ошибки, и логика должна быть похожа на другие плакаты (или вы можете положить if ($line =~ /^\s*$/) в качестве вашего if).

Если файл, вам просто нужно проверить if (!$lctr) {}после конец Вашего цикла - как отмечалось в другом ответе, цикл не будет введен, если нет ни одной строки в файле.

2

Вы можете попробовать отладки:

... 
chomp; 

use Data::Dumper; 
$Data::Dumper::Useqq = 1; 

print Dumper({ "line is" => $_ }); 
my @line = split/,/; 
print Dumper({ "split into" => \@line }); 

if ([email protected]) { 
... 
+1

И, конечно, всегда ** всегда ** использовать 'use strict; использовать предупреждения, 'в каждом отдельном файле. – Ether

Смежные вопросы