如何从命令行获取文件句柄?

时间:2008-10-09 21:32:28

标签: perl filehandle

我有一个以文件句柄作为参数的子程序。如何从命令行上指定的文件路径创建文件句柄?我不想自己对这个文件进行任何处理,我只是想把它传递给另一个子程序,它返回一个哈希数组,包含文件中所有已解析的数据。

以下是我正在使用的命令行输入:

$ ./getfile.pl /path/to/some/file.csv

以下是我调用的子程序的开头:

sub parse {
    my $handle = shift;
    my @data   = <$handle>;
    while (my $line = shift(@data)) {
      # do stuff
    }
}

4 个答案:

答案 0 :(得分:16)

命令行参数在预定义的@ARGV数组中可用。您可以从那里获取文件名,并使用open打开文件句柄。假设您希望对文件进行只读访问,则可以这样做:

my $file = shift @ARGV;
open(my $fh, '<', $file) or die "Can't read file '$file' [$!]\n";
parse($fh);

请注意,or die...会检查调用open是否成功,如果不是,则会显示错误消息。内置变量$!将包含失败时(OS相关的)错误消息,告知您调用未成功的原因。例如“许可被拒绝。”

答案 1 :(得分:5)

parse(*ARGV)是最简单的解决方案:解释有点长,但学习如何有效使用Perl的一个重要部分是学习Perl。

当你使用空文件句柄(<>)时,它实际上从神奇的ARGV文件句柄中读取,它具有特殊的语义:它从@ARGV中命名的所有文件中读取,或者如果STDIN为空,则@ARGV

来自perldoc perlop

  

空文件句柄<>很特殊:它可以用来模拟   sed和awk的行为。来自<>的输入来自标准   输入,或来自命令行中列出的每个文件。这是怎么回事   有效:第一次评估<>时,会检查@ARGV数组,以及   如果它为空,$ARGV[0]设置为"-",打开后会显示给您   标准输入。然后将@ARGV数组作为列表处理   文件名。循环

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

等效于以下类似Perl的伪代码:

unshift(@ARGV, '-') unless @ARGV;
while ($ARGV = shift) {
    open(ARGV, $ARGV);
    while (<ARGV>) {
        ...         # code for each line
    }
}
     

除了说它并不那么麻烦,并且实际上会有效。它   确实会移动@ARGV数组并将当前文件名放入   $ARGV变量。它还在内部使用文件句柄ARGV - <>只是一个   <ARGV>的同义词,这是神奇的。 (上面的伪代码没有   工作,因为它将<ARGV>视为非魔法。)

您不必在<>循环中使用while - my $data = <>会从第一个非空文件中读取一行,my @data = <>;会将其淹没一下子就可以了,你可以传递*ARGV,好像它是一个普通的文件句柄。

答案 2 :(得分:1)

这是-n开关的用途!

采用你的解析方法,并执行以下操作:

#!/usr/bin/perl -n

#do stuff

每一行都存储在$ _中。所以你运行

./ getfile.pl /path/to.csv

它就是这样做的。

有关这些内容的详情,请参阅herehere。我也喜欢-p,并且发现-a和-F的组合非常有用。

此外,如果您想进行一些额外的处理,请添加BEGIN和结束块。

#!/usr/bin/perl -n

BEGIN {
  my $accumulator;
}

# do stuff

END {
  print process_total($accumulator);
}

或其他什么。这非常非常有用。

答案 3 :(得分:-1)

我错过了什么,或者你只是在寻找open()电话?

open($fh, "<$ARGV[0]") or die "couldn't open $ARGV[0]: $!";
do_something_with_fh($fh);
close($fh);