perl拆分空文件

时间:2010-05-06 16:09:07

标签: perl

我基本上有以下我正在使用的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的新手所以很可能在这里错过了一些简单的东西。

5 个答案:

答案 0 :(得分:5)

  1. 如果文件为空,则while循环体将根本不运行。
  2. 在标量上下文中计算数组会返回数组中的元素数。

    如果定义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)

以下是一些使您的代码更加惯用的提示:

  • special variable $.已保留当前行号,因此您可能会删除$lctr
  • 空行是否真的错误,或者你可以忽略它们吗?
  • 拉开从split返回的列表并提供各个部分名称。
  • 让Perl使用"diamond operator"
  • 进行开场
  

空文件句柄<>很特殊:它可用于模拟sedawk的行为。 <>的输入来自标准输入,或来自命令行中列出的每个文件。以下是它的工作原理:第一次评估<>时,会检查@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) {} - 如另一个答案中所述,如果文件中没有行,则不会输入循环