код завершения вызова system () с единственным скалярным аргументом в Perl - PullRequest
2 голосов
/ 22 ноября 2011

В скрипте Perl с несколькими каналами используется вызов system() с использованием одного скалярного аргумента.Вызов выглядит примерно так:

system("zcat /foo.gz | grep '^.{6}X|Y|Z' | awk '{print $2,$3,$4,$6}' | bzip2 > /foo.processed.bz2");

Файл, о котором идет речь (foo.gz), довольно большой, сжатый размер около 2 ГБ.Я думаю, именно поэтому изначально это было сделано с помощью системного вызова.

Вопросы:

Проблема в том, что этот системный вызов всегда, кажется, возвращает 0из системных команд сбой или нет.Я предполагаю, что это потому, что он вызывается через sh -c '...'.Это правильно?

Есть ли способ проверить, был ли вызов system() успешным, если передан только один скалярный аргумент?

Есть ли лучший способ обработки большого файла, такой какэто в равной степени или более эффективно (главным образом, в отношении скорости)?

Спасибо за любые подсказки, так как я не очень знаком с Perl.

Ответы [ 4 ]

3 голосов
/ 22 ноября 2011

Две вещи:

  1. Когда вы делаете системный вызов, возвращаемое значение является последним значением в конвейере. Таким образом, вы получаете код состояния команды bzip2.
  2. Причина, по которой программа делает это, заключается в том, что люди, написавшие программу, вероятно, не знали ничего лучше. Я видел, как Perl-программы используют системные вызовы для поиска базового имени файла, поиска и даже копирования / переименования / перемещения. Это все, что можно сделать быстрее и проще в программе Perl. И у вас нет проблем совместимости с Windows / Unix.

Вам всегда лучше использовать модули Perl для подобных вещей. В этом случае я уверен, что модули Perl будут работать быстрее, чем конвейер оболочки, и у вас будет больше контроля над всей операцией.

Существует набор под названием IO :: Compress , который может обрабатывать как Zip, так и BZip2.

Я использую Archive :: Zip , который является отличным модулем, но вы хотите использовать алгоритм сжатия Bzip2, а Archive::Zip не может справиться с этим.

2 голосов
/ 22 ноября 2011

system() возвращает то, что возвращает оболочка /bin/sh. Когда несколько команд передаются по конвейеру, оболочка разветвляет новый процесс для каждой из них, и возвращается код состояния последней команды в цепочке, в данном случае bzip2.

1 голос
/ 22 ноября 2011

Исходя из ваших комментариев и ответов, я бы сделал это сейчас:

$infile =~ s/(.*\.gz)\s*$/gzip -dc < $1|/;
open(OUTFH, "| /bin/bzip > $outfile") or die "Can't open $outfile: $!";
open(INFH, $infile) or die "Can't open $infile: $!";
while (my $line = <INFH>) {
    if ($line =~ /^.{6}X|Y|Z) {
        # TODO: the awk part...
        print OUTFH $line;
    }
}
close(INFH);
close(OUTFH);

Пожалуйста, не стесняйтесь комментировать и голосовать "вверх / вниз".

0 голосов
/ 22 ноября 2011

Вам лучше выполнять обработку текста из самого perl - для этого и нужен perl :)

system () только когда-либо возвращает 0 или 1. Чтобы захватить фактический вывод, попробуйте вызвать его с помощью обратных кавычек:`команда`, а не система ('команда')

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...