我基本上有以下我正在使用的perl:
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;
}
}
如果给出一个空文件,我无法确定split /,/函数返回的内容。代码块if(!@line)永远不会被执行。如果我将其改为
if (@line)
执行代码块。我已经阅读了关于perl split功能的信息 http://perldoc.perl.org/functions/split.html以及关于测试空数组的讨论here但不确定这里发生了什么。
我是Perl的新手所以很可能在这里错过了一些简单的东西。
答案 0 :(得分:5)
在标量上下文中计算数组会返回数组中的元素数。
如果定义split /,/
, $_
始终会返回1+元素列表。
答案 1 :(得分:2)
您可以尝试一些调试:
...
chomp;
use Data::Dumper;
$Data::Dumper::Useqq = 1;
print Dumper( { "line is" => $_ } );
my @line = split/,/;
print Dumper( { "split into" => \@line } );
if (!@line) {
...
答案 2 :(得分:1)
以下是一些使您的代码更加惯用的提示:
$.
已保留当前行号,因此您可能会删除$lctr
。split
返回的列表并提供各个部分名称。空文件句柄
<>
很特殊:它可用于模拟sed
和awk
的行为。<>
的输入来自标准输入,或来自命令行中列出的每个文件。以下是它的工作原理:第一次评估<>
时,会检查@ARGV
数组,如果它为空,$ARGV[0]
设置为"-"
,打开时会给出@ARGV
你的标准输入。然后将while (<>) { ... # code for each line }
数组作为文件名列表处理。循环unshift(@ARGV, '-') unless @ARGV; while ($ARGV = shift) { open(ARGV, $ARGV); while (<ARGV>) { ... # code for each line } }
等效于以下类似Perl的伪代码:
input
除了说它并不那么麻烦,并且实际上会有效。
假设您的输入位于名为#! /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";
}
且包含
Campbell's soup,0.50 Mac & Cheese,0.25
然后用
{{1}}
我们在Unix上运行如下:
$ ./coupons input Campbell's soup => 0.50 Mac & Cheese => 0.25
答案 3 :(得分:0)
空文件或空行?无论如何,请尝试此测试而不是!@line
。
if (scalar(@line) == 0) {
...
}
scalar
方法以perl返回数组的长度。
一些澄清:
if (@line) {
}
与:
相同if (scalar(@line)) {
}
在标量上下文中,数组(@line
)返回数组的长度。因此scalar(@line)
强制@line
在标量上下文中进行求值并返回数组的长度。
答案 4 :(得分:0)
我不确定您是否正在尝试检测该行是否为空(您的代码正在尝试)或整个文件是否为空(这就是错误所说的内容)。
如果该行,请修正您的错误文本,逻辑应该像其他海报所说的那样(或者您可以将if ($line =~ /^\s*$/)
作为if)。
如果是文件,您只需在循环结束后之后测试if (!$lctr) {}
- 如另一个答案中所述,如果文件中没有行,则不会输入循环