Perl split into empty file

I have basically the following perl that I am 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 figuring out what the split / function returns, / if it is assigned an empty file. The if (! @Line) code block is never executed. If I change this as

if (@line)

      

than the code block is executed. I've read the information about perl splitting function at http://perldoc.perl.org/functions/split.html and the discussion here about testing on an empty array, but not sure what is going on here.

I'm new to Perl, so there probably isn't anything simple here.

+2


a source to share


5 answers


Here are some tips to make your code more idiomatic:

File descriptor null <>

is special: it can be used to emulate the behavior of sed

and awk

. Input from <>

comes either from standard input or from each file specified on the command line. Here's how it works: the first time the <>

array is evaluated @ARGV

, and if it is empty, it is $ARGV[0]

set to "-"

, which gives you standard input when opened. The array is @ARGV

then processed as a list of filenames. Cycle

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

      

is equivalent to the following Perl-like pseudocode:

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

      

except that it is not that cumbersome to say and will actually work.

Say your input is in a file named input

and contains

Campbell 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";
}

      

which we run as shown below on Unix:

$ ./coupons input
Campbell soup => 0.50
Mac & Cheese => 0.25
+1


a source


  • If the file is empty, the body of the while loop will not work at all.
  • Evaluating an array in a scalar context returns the number of elements in the array.

    split /,/

    always returns a list of 1+ items if $_

    defined.



+5


a source


You can try debugging:

...
chomp;

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

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

if (!@line) {
...

      

+2


a source


Empty file or empty line? Regardless, try this test instead !@line

.

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

      

The method scalar

returns the length of the array in perl.

Some clarifications:

if (@line) {
}

      

Same as:

if (scalar(@line)) {
}

      

In scalar context, arrays ( @line

) return the length of the array. Therefore scalar(@line)

forces the @line

evaluation in a scalar context and returns the length of the array.

0


a source


I'm not sure if you are trying to determine if the line is empty (which is what your code is trying to do) or the entire file is empty (which is what the error says).

If string please correct the error text and the logic should be similar to other posters (or you can put if ($line =~ /^\s*$/)

as your if).

If you want a file, you just need to check if (!$lctr) {}

after the end of your loop - as noted in another answer, the loop will not be entered if there are no lines in the file.

0


a source







All Articles