简体   繁体   English

perl拆分空文件

[英]perl split on empty file

I have basically the following perl I'm working with: 我基本上有以下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;
 }
}

I'm having trouble determining what the split/,/ function is returning if an empty file is given to it. 如果给出一个空文件,我无法确定split /,/函数返回的内容。 The code block if (!@line) is never being executed. 代码块if(!@line)永远不会被执行。 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. 我读过的关于perl的分割功能对信息http://perldoc.perl.org/functions/split.html和讨论, 这里大约测试空数组,但不知道是怎么回事。

I am new to Perl so am probably missing something straightforward here. 我是Perl的新手,所以我可能在这里错过了一些简单明了的东西。

  1. If the file is empty, the while loop body will not run at all. 如果文件为空,则while循环体将根本不运行。
  2. Evaluating an array in scalar context returns the number of elements in the array. 在标量上下文中计算数组会返回数组中的元素数。

    split /,/ always returns a 1+ elements list if $_ is defined. split /,/如果定义$_则始终返回1+元素列表。

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) {
...

Below are a few tips to make your code more idiomatic: 以下是一些使您的代码更加惯用的提示:

  • The special variable $. 特殊变量$. already holds the current line number, so you can likely get rid of $lctr . 已经保存当前行号,因此您可以摆脱$lctr
  • Are empty lines really errors, or can you ignore them? 空行真的是错误,还是你可以忽略它们?
  • Pull apart the list returned from split and give the pieces names. 拉开从split返回的列表并给出各个部分的名称。
  • Let Perl do the opening with the "diamond operator" : 让Perl与“钻石运营商”一起开场:

The null filehandle <> is special: it can be used to emulate the behavior of sed and awk . null filehandle <>是特殊的:它可以用来模拟sedawk的行为。 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. 以下是它的工作原理:第一次计算<> ,检查@ARGV数组,如果它是空的,则将$ARGV[0]设置为"-" ,打开时会为您提供标准输入。 The @ARGV array is then processed as a list of filenames. 然后将@ARGV数组作为文件名列表处理。 The loop 循环

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

is equivalent to the following Perl-like pseudo code: 等效于以下类似Perl的伪代码:

 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 假设您的输入位于名为input且包含的文件中

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: 我们在Unix上运行如下:

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

Empty file or empty line? 空文件还是空行? Regardless, try this test instead of !@line . 无论如何,尝试这个测试而不是!@line

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

The scalar method returns the array's length in perl. scalar方法以perl形式返回数组的长度。

Some clarification: 一些澄清:

if (@line) {
}

Is the same as: 是相同的:

if (scalar(@line)) {
}

In a scalar context, arrays ( @line ) return the length of the array. 在标量上下文中,数组( @line )返回数组的长度。 So scalar(@line) forces @line to evaluate in a scalar context and returns the length of the array. 因此scalar(@line)强制@line在标量上下文中进行求值并返回数组的长度。

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 ($line =~ /^\\s*$/)作为你的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. 如果是文件,你只需要在循环结束测试if (!$lctr) {} - 如另一个答案中所述,如果文件中没有行,则不会输入循环。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM