Reputation:
I have basically the following perl I'm working with:
open I,$coupon_file or die "Error: File $coupon_file will not Open: $! \n";
while (<I>) {
$lctr++;
chomp;
my @line = split/,/;
if (!@line) {
print E "Error: $coupon_file is empty!\n\n";
$processFile = 0; last;
}
}
I'm having trouble determining what the split/,/ function is returning if an empty file is given to it. The code block if (!@line) is never being executed. If I change that to be
if (@line)
than the code block is executed. I've read information on the perl split function over at http://perldoc.perl.org/functions/split.html and the discussion here about testing for an empty array but not sure what is going on here.
I am new to Perl so am probably missing something straightforward here.
Upvotes: 2
Views: 563
Reputation: 139441
Below are a few tips to make your code more idiomatic:
$.
already holds the current line number, so you can likely get rid of $lctr
.split
and give the pieces names.The null filehandle
<>
is special: it can be used to emulate the behavior ofsed
andawk
. Input from<>
comes either from standard input, or from each file listed on the command line. Here's how it works: the first time<>
is evaluated, the@ARGV
array is checked, and if it is empty,$ARGV[0]
is set to"-"
, which when opened gives you standard input. The@ARGV
array is then processed as a list of filenames. The loopwhile (<>) { ... # code for each line }
is equivalent to the following Perl-like pseudo code:
unshift(@ARGV, '-') unless @ARGV; while ($ARGV = shift) { open(ARGV, $ARGV); while (<ARGV>) { ... # code for each line } }
except that it isn't so cumbersome to say, and will actually work.
Say your input is in a file named input
and contains
Campbell's soup,0.50 Mac & Cheese,0.25
Then with
#! /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";
}
that we run as below on Unix:
$ ./coupons input Campbell's soup => 0.50 Mac & Cheese => 0.25
Upvotes: 1
Reputation: 98388
You might try some debugging:
...
chomp;
use Data::Dumper;
$Data::Dumper::Useqq = 1;
print Dumper( { "line is" => $_ } );
my @line = split/,/;
print Dumper( { "split into" => \@line } );
if (!@line) {
...
Upvotes: 2
Reputation: 129383
I'm not sure whether you're trying to detect if the line is empty (which your code is trying to) or whether the whole file is empty (which is what the error says).
If the line, please fix your error text and the logic should be like the other posters said (or you can put if ($line =~ /^\s*$/)
as your if).
If the file, you simply need to test if (!$lctr) {}
after the end of your loop - as noted in another answer, the loop will not be entered if there's no lines in the file.
Upvotes: 0
Reputation: 6375
Empty file or empty line? Regardless, try this test instead of !@line
.
if (scalar(@line) == 0) {
...
}
The scalar
method returns the array's length in perl.
Some clarification:
if (@line) {
}
Is the same as:
if (scalar(@line)) {
}
In a scalar context, arrays (@line
) return the length of the array. So scalar(@line)
forces @line
to evaluate in a scalar context and returns the length of the array.
Upvotes: 0
Reputation: 149756
Evaluating an array in scalar context returns the number of elements in the array.
split /,/
always returns a 1+ elements list if $_
is defined.
Upvotes: 5