代码之家  ›  专栏  ›  技术社区  ›  cowgod

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

  •  3
  • cowgod  · 技术社区  · 16 年前

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

    我使用的命令行输入如下所示:

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

    下面是我调用的子例程的开头:

    sub parse {
        my $handle = shift;
        my @data   = <$handle>;
        while (my $line = shift(@data)) {
          # do stuff
        }
    }
    
    4 回复  |  直到 16 年前
        1
  •  16
  •   Michael Carman    16 年前

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

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

    请注意 or die... 检查呼叫 打开 如果没有,则返回错误消息。内置变量 $! 将包含失败时的(依赖于操作系统)错误消息,告诉您呼叫失败的原因。例如,“许可被拒绝”。

        2
  •  5
  •   ephemient    16 年前

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

    当使用空文件句柄时( <> ,它实际上是从魔法书中读到的。 ARGV filehandle,具有特殊的语义:它从中命名的所有文件读取 @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 & GT; 作为非魔法。)

    你不必使用 <> 在一个 while 循环—— my $data = <> 将从第一个非空文件读取一行, my @data = <>; 会一下子把它全吐出来,你就可以过去了 *ARGV 就像一个普通的文件句柄。

        3
  •  1
  •   Steve Klabnik    16 年前

    这就是-n开关的作用!

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

    #!/usr/bin/perl -n
    
    #do stuff
    

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

    /getfile.pl/path/to.csv

    它能做到这一点。

    here here 有关这些的更多信息。我也喜欢-p,并且发现-a和-f的组合非常有用。

    另外,如果您想做一些额外的处理,请添加开始和结束块。

    #!/usr/bin/perl -n
    
    BEGIN {
      my $accumulator;
    }
    
    # do stuff
    
    END {
      print process_total($accumulator);
    }
    

    或者什么。这非常非常有用。

        4
  •  -1
  •   bmdhacks    16 年前

    我是丢失了什么,还是您只是在寻找open()调用?

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