18

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

我认为它将它们连接在一个文件中,并且逐行工作。问题是,我怎么知道我正在使用第一个文件?然后是第二个。

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

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

3 回答 3

21

菱形运算符不连接文件,它只是打开并连续读取它们。你如何控制它取决于你需要如何控制它。检查我们何时读取文件的最后一行的一种简单方法是使用eof

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

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

$counter++ if eof;

请注意,此计数将在文件的最后一行增加一,因此不要过早使用它。

如果要跟踪$.当前文件句柄中的行号,可以close通过 ARGV 文件句柄重置此计数器:

while (<>) {
    print "line $. : ", $_;
    close ARGV if eof;
}
于 2013-02-17T15:24:58.977 回答
12

<>是 readline 运算符的一个特例。它通常需要一个文件句柄:<$fh>.

如果忽略文件句柄,则ARGV使用魔术文件句柄。

如果没有给出命令行参数,那么ARGVis STDIN。如果给出了命令行参数,则将依次ARGV传递open给每个参数。这类似于

# Pseudocode
while ($ARGV = shift @ARGV) {
  open ARGV, $ARGV or do{
    warn "Can't open $ARGV: $!";
    next;
  };
  while (<ARGV>) {
    ...; # your code
  }
}

$ARGV变量是真实的,并保存当前打开的文件的文件名。

请注意,两个参数的形式open(可能在幕后使用)是非常不安全的。文件名rm -rf * |可能不符合您的要求。

于 2013-02-17T15:08:41.950 回答
2

当前文件的名称<>包含在特殊$ARGV 变量中。

您可以将参数数组中的文件列表与当前文件名交叉匹配,@ARGV以获取文件在列表中的位置。假设您期望的唯一参数是文件名,您可以简单地执行以下操作:

my %filename_positions = map { ( $ARGV[$_] => $_ ) } 0..$#ARGV;

while (<>) {
    my $file_number = $filename_positions{$ARGV};
    #... if ($file_number == 0) { #first file     
}
于 2013-02-17T15:08:58.447 回答