我有一个以文件句柄作为参数的子程序。如何从命令行上指定的文件路径创建文件句柄?我不想自己对这个文件进行任何处理,我只是想把它传递给另一个子程序,它返回一个哈希数组,包含文件中所有已解析的数据。
以下是我正在使用的命令行输入:
$ ./getfile.pl /path/to/some/file.csv
以下是我调用的子程序的开头:
sub parse {
my $handle = shift;
my @data = <$handle>;
while (my $line = shift(@data)) {
# do stuff
}
}
答案 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
它就是这样做的。
有关这些内容的详情,请参阅here和here。我也喜欢-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);