Perl - while (<>) 文件处理

19

一个简单的程序使用 while( <> ) 处理作为参数给定的文件(./program 1.file 2.file 3.file)和Unix系统标准输入。

我认为它将这些文件连接在一起并逐行处理。问题是,如何知道我正在处理第一个文件?接下来是第二个文件。

举个简单的例子,我想把文件内容打印在一行中。

while( <> ){
    print "\n" if (it's the second file already);
    print $_;
}

2
看起来与以下的SO主题非常相似:https://dev59.com/nGYr5IYBdhLWcg3wi63d - varnie
3个回答

22

钻石操作符并不会连接文件,它只是按顺序打开和读取它们。如何控制这一点取决于您需要如何进行控制。检查我们是否已经读取了文件的最后一行的一个简单方法是使用eof

while (<>) {
    chomp;             # remove newline
    print;             # print the line
    print "\n" if eof; # at end of file, print a newline
}

您还可以考虑使用计数器来跟踪您正在处理的文件的顺序。

$counter++ if eof;
注意,文件的最后一行会使该计数器增加1,因此不要过早使用它。
如果您想跟踪当前文件句柄中行号$.,可以close ARGV 文件句柄以重置此计数器:
while (<>) {
    print "line $. : ", $_;
    close ARGV if eof;
}

请参阅 perldoc -f eof 以获取有关如何检测由 <> 运算符读取的文件之间边界的更多信息。 - chepner

13
<>是readline操作符的一种特殊情况。通常需要提供一个文件句柄:<$fh>
如果省略文件句柄,则会使用魔法变量ARGV文件句柄。
如果没有给出命令行参数,则ARGV表示标准输入STDIN。如果给出了命令行参数,则ARGV将依次被打开。这类似于...
# Pseudocode
while ($ARGV = shift @ARGV) {
  open ARGV, $ARGV or do{
    warn "Can't open $ARGV: $!";
    next;
  };
  while (<ARGV>) {
    ...; # your code
  }
}
$ARGV变量是真实存在的,它保存了当前打开文件的文件名。
请注意,open的两个参数形式(在这里可能在幕后使用)是相当不安全的。文件名rm -rf * |可能不会做你想要的事情。

2
当前文件的名称对于<>被包含在特殊的$ARGV变量中。
您可以将@ARGV参数数组中的文件列表与当前文件名进行交叉匹配,以获取文件在列表中的位置。假设您期望的唯一参数是文件名,那么您可以简单地执行以下操作:
my %filename_positions = map { ( $ARGV[$_] => $_ ) } 0..$#ARGV;

while (<>) {
    my $file_number = $filename_positions{$ARGV};
    #... if ($file_number == 0) { #first file     
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接