Como posso capturar o comando stdin e stdout do sistema a partir de um script Perl?

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

  •  09-06-2019
  •  | 
  •  

Pergunta

No meio de um script Perl, há um comando de sistema que desejo executar.Eu tenho uma string que contém os dados que precisam ser inseridos no stdin (o comando só aceita entrada do stdin) e preciso capturar a saída gravada no stdout.Examinei os vários métodos de execução de comandos do sistema em Perl e o open function parece ser o que eu preciso, exceto que parece que só consigo capturar stdin ou stdout, não ambos.

No momento, parece que minha melhor solução é usar open, redirecione o stdout para um arquivo temporário e leia o arquivo após a conclusão do comando.Existe uma solução melhor?

Foi útil?

Solução

Acho que você quer dar uma olhada IPC::Aberto2

Outras dicas

IPC::Open2/3 estão bem, mas descobri que geralmente tudo que eu realmente preciso é IPC::Run3, que lida muito bem com casos simples com complexidade mínima:

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

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

A documentação compara IPC::Run3 com outras alternativas.Vale a pena ler mesmo que você não decida usá-lo.

O documentação perlipc aborda muitas maneiras de fazer isso, incluindo IPC::Open2 e IPC::Open3.

Em algum lugar no topo do seu script, inclua a linha

use IPC::Open2;

Isso incluirá o módulo necessário, geralmente instalado com a maioria das distribuições Perl por padrão.(Se não tiver, você pode instalá-lo usando CPAN.) Então, em vez de abrir, chame:

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

Você pode enviar dados para o seu comando enviando-os para $cmd_in e depois ler a saída do seu comando lendo $cmd_out.

Se você também quiser ler o fluxo stderr do comando, você pode usar o módulo IPC::Open3.

IPC::Open3 provavelmente faria o que você deseja.Pode capturar STDERR e STDOUT.

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

Uma maneira muito fácil de fazer isso que descobri recentemente é o IPC::Filtro módulo.Ele permite que você faça o trabalho de forma extremamente intuitiva:

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

Observe como ele invoca seu comando sem passar pelo shell se você passar uma lista.Ele também faz um trabalho razoável no tratamento de erros em utilitários comuns.(Em caso de falha, dies, usando o texto de STDERR como mensagem de erro;em caso de sucesso, STDERR é simplesmente descartado.)

Obviamente, não é adequado para grandes quantidades de dados, pois não oferece nenhuma maneira de realizar qualquer processamento de streaming;além disso, o tratamento de erros pode não ser granular o suficiente para suas necessidades.Mas faz com que muitos casos simples sejam realmente realmente simples.

Existe um comando perl especial para isso

open2()

Mais informações podem ser encontradas em: http://sunsite.ualberta.ca/Documentation/Misc/perl-5.6.1/lib/IPC/Open2.html

Se você não quiser incluir pacotes extras, basta fazer

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

o que é o contrário do que você sugeriu, mas também deve funcionar.

Eu sempre faço isso dessa maneira se espero apenas uma única linha de saída ou quero dividir o resultado em algo diferente de uma nova linha:

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

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

Se você quiser lidar com uma resposta multilinha, obtenha o resultado como um array:

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

foreach ( my $line ) (@lines) {  
    if ( $line =~ /some pattern/ ) {  
        do_something();  
    }  
}  
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top