3

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

这是我正在使用的命令行输入的样子:

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

这是我正在调用的子程序的开头部分:

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

4 回答 4

16

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

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

请注意,or die...检查调用open是否成功,如果不是,则会显示错误消息。内置变量$!将包含(取决于操作系统的)失败错误消息,告诉您调用不成功的原因。例如“权限被拒绝”。

于 2008-10-09T21:39:00.310 回答
5

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

当您使用空文件句柄 ( <>) 时,它实际上是从ARGV具有特殊语义的神奇文件句柄中读取的:它从名为 in 的所有文件中读取@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像普通文件句柄一样传递。

于 2008-10-10T01:42:53.997 回答
1

这就是 -n 开关的用途!

采用您的 parse 方法,然后执行以下操作:

#!/usr/bin/perl -n

#do stuff

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

./getfile.pl /path/to.csv

它做到了这一点。

有关这些的更多信息,请参见此处此处。我也喜欢 -p,并且发现 -a 和 -F 的组合非常有用。

此外,如果您想做一些额外的处理,请添加 BEGIN 和 end 块。

#!/usr/bin/perl -n

BEGIN {
  my $accumulator;
}

# do stuff

END {
  print process_total($accumulator);
}

管他呢。这是非常非常有用的。

于 2008-10-10T20:14:57.017 回答
-1

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

open($fh, "<$ARGV[0]") or die "couldn't open $ARGV[0]: $!";
do_something_with_fh($fh);
close($fh);
于 2008-10-09T21:36:16.837 回答