Как я могу захватить стандартный ввод и вывод системной команды из сценария Perl?

StackOverflow https://stackoverflow.com/questions/78091

  •  09-06-2019
  •  | 
  •  

Вопрос

В середине сценария Perl есть системная команда, которую я хочу выполнить.У меня есть строка, содержащая данные, которые необходимо передать на стандартный ввод (команда принимает входные данные только со стандартного ввода), и мне нужно захватить вывод, записанный на стандартный вывод.Я рассмотрел различные методы выполнения системных команд в Perl и open Кажется, это то, что мне нужно, за исключением того, что похоже, что я могу захватывать только стандартный ввод или стандартный вывод, а не оба.

На данный момент кажется, что мое лучшее решение - использовать open, перенаправить стандартный вывод во временный файл и прочитать из файла после завершения команды.Есть ли лучшее решение?

Это было полезно?

Решение

Я думаю, ты хочешь взглянуть на МПК::Open2

Другие советы

IPC::Open2/3 — это нормально, но я обнаружил, что обычно все, что мне действительно нужно, — это МПК::Run3, который очень хорошо справляется с простыми случаями с минимальной сложностью:

use IPC::Run3;    # Exports run3() by default

run3( \@cmd, \$in, \$out, \$err );

В документации IPC::Run3 сравнивается с другими альтернативами.Эту книгу стоит прочитать, даже если вы не решите ее использовать.

А документация по перлипку охватывает множество способов сделать это, включая IPC::Open2 и IPC::Open3.

Где-нибудь в верхней части вашего скрипта добавьте строку

use IPC::Open2;

Он будет включать необходимый модуль, который обычно устанавливается в большинстве дистрибутивов Perl по умолчанию.(Если у вас его нет, вы можете установить его с помощью CPAN.) Затем вместо открытия вызовите:

$pid = open2($cmd_out, $cmd_in, 'some cmd and args');

Вы можете отправить данные своей команде, отправив их в $cmd_in, а затем прочитать вывод своей команды, прочитав их из $cmd_out.

Если вы также хотите иметь возможность читать поток stderr команды, вместо этого вы можете использовать модуль IPC::Open3.

IPC::Open3, вероятно, сделает то, что вы хотите.Он может захватывать STDERR и STDOUT.

http://metacpan.org/pod/IPC::Open3

Недавно я нашел очень простой способ сделать это: тот МПК::Фильтр модуль.Это позволяет выполнять работу чрезвычайно интуитивно:

$output = filter $input, 'somecmd', '--with', 'various=args', '--etc';

Обратите внимание, как он вызывает вашу команду, не проходя через оболочку, если вы передаете ей список.Он также выполняет разумную работу по обработке ошибок для распространенных утилит.(В случае неудачи это dies, используя текст из STDERR в качестве сообщения об ошибке;в случае успеха STDERR просто отбрасывается.)

Конечно, он не подходит для огромных объемов данных, поскольку не обеспечивает никакой потоковой обработки;кроме того, обработка ошибок может оказаться недостаточно детальной для ваших нужд.Но это делает многие простые случаи действительно Действительно простой.

Для этого есть специальная команда Perl.

open2()

Более подробную информацию можно найти на: http://sunsite.ualberta.ca/Documentation/Misc/perl-5.6.1/lib/IPC/Open2.html

Если вы не хотите включать дополнительные пакеты, вы можете просто сделать

open(TMP,">tmpfile");
print TMP  $tmpdata ;
open(RES,"$yourcommand|");
$res = "" ;
while(<RES>){
$res .= $_ ;
}

что противоречит тому, что вы предложили, но тоже должно работать.

Я всегда делаю это таким образом, если ожидаю только одну строку вывода или хочу разделить результат на что-то другое, кроме новой строки:

my $result = qx( command args 2>&1 );  
my $rc=$?;  
# $rc >> 8 is the exit code of the called program.

if ($rc != 0 ) {  
    error();  
}  

Если вы хотите иметь дело с многострочным ответом, получите результат в виде массива:

my @lines = qx( command args 2>&1 );  

foreach ( my $line ) (@lines) {  
    if ( $line =~ /some pattern/ ) {  
        do_something();  
    }  
}  
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top