Как получить дескриптор файла из командной строки? - PullRequest
3 голосов
/ 10 октября 2008

У меня есть подпрограмма, которая принимает дескриптор файла в качестве аргумента. Как сделать дескриптор файла из пути к файлу, указанному в командной строке? Я не хочу выполнять какую-либо обработку этого файла самостоятельно, я просто хочу передать его другой подпрограмме, которая возвращает массив хэшей со всеми проанализированными данными из файла.

Вот как выглядит ввод командной строки:

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

Вот как выглядит начало подпрограммы, которую я вызываю:

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

Ответы [ 4 ]

16 голосов
/ 10 октября 2008

Аргументы командной строки доступны в предопределенном массиве @ARGV. Вы можете получить имя файла оттуда и использовать open, чтобы открыть для него дескриптор файла. Предполагая, что вам нужен доступ только для чтения к файлу, вы бы сделали это следующим образом:

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

Обратите внимание, что or die... проверяет вызов open на успешность и умирает с сообщением об ошибке, если это не так. Встроенная переменная $! будет содержать (зависящее от ОС) сообщение об ошибке при сбое, которое сообщает вам, почему вызов не был успешным. например «В доступе отказано».

5 голосов
/ 10 октября 2008

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, как если бы это был обычный дескриптор файла.

1 голос
/ 11 октября 2008

Для этого нужен ключ -n!

Возьмите метод разбора и сделайте следующее:

#!/usr/bin/perl -n

#do stuff

Каждая строка хранится в $ _. Итак, вы бежите

. / Getfile.pl /path/to.csv

И это делает.

См. здесь и здесь для получения дополнительной информации об этом. Мне тоже нравится -p, и я считаю, что комбинации -a и -F очень полезны.

Также, если вы хотите выполнить дополнительную обработку, добавьте BEGIN и завершающие блоки.

#!/usr/bin/perl -n

BEGIN {
  my $accumulator;
}

# do stuff

END {
  print process_total($accumulator);
}

или что угодно. Это очень, очень полезно.

0 голосов
/ 10 октября 2008

Я что-то упустил или вы просто ищете вызов open ()?

open($fh, "<$ARGV[0]") or die "couldn't open $ARGV[0]: $!";
do_something_with_fh($fh);
close($fh);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...