¿Cómo puedo capturar la entrada estándar y la salida estándar del comando del sistema desde un script Perl?

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

  •  09-06-2019
  •  | 
  •  

Pregunta

En medio de un script Perl, hay un comando del sistema que quiero ejecutar.Tengo una cadena que contiene los datos que deben introducirse en la entrada estándar (el comando solo acepta entradas de la entrada estándar) y necesito capturar la salida escrita en la salida estándar.He analizado los diversos métodos para ejecutar comandos del sistema en Perl y el open La función parece ser lo que necesito, excepto que parece que solo puedo capturar stdin o stdout, no ambos.

Por el momento, parece que mi mejor solución es usar open, redirige stdout a un archivo temporal y lee el archivo una vez que finaliza el comando.¿Existe una solución mejor?

¿Fue útil?

Solución

Creo que quieres echarle un vistazo IPC::Abierto2

Otros consejos

IPC::Open2/3 están bien, pero descubrí que normalmente todo lo que realmente necesito es IPC::Ejecutar3, que maneja muy bien los casos simples con una complejidad mínima:

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

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

La documentación compara IPC::Run3 con otras alternativas.Vale la pena leerlo incluso si no decides usarlo.

El documentación perlipc cubre muchas formas de hacer esto, incluidas IPC::Open2 e IPC::Open3.

En algún lugar de la parte superior de tu guión, incluye la línea

use IPC::Open2;

Eso incluirá el módulo necesario, generalmente instalado con la mayoría de las distribuciones de Perl de forma predeterminada.(Si no lo tiene, puede instalarlo usando CPAN). Luego, en lugar de abrir, llame a:

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

Puede enviar datos a su comando enviándolos a $cmd_in y luego leer la salida de su comando leyendo desde $cmd_out.

Si también desea poder leer la secuencia stderr del comando, puede usar el módulo IPC::Open3 en su lugar.

IPC::Open3 probablemente haría lo que quieras.Puede capturar STDERR y STDOUT.

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

Una manera muy fácil de hacer esto que encontré recientemente es el IPC::Filtro módulo.Te permite hacer el trabajo de forma extremadamente intuitiva:

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

Observe cómo invoca su comando sin pasar por el shell si le pasa una lista.También hace un trabajo razonable al manejar errores para servicios públicos comunes.(En caso de falla, dies, utilizando el texto de STDERR como mensaje de error;en caso de éxito, STDERR simplemente se descarta).

Por supuesto, no es adecuado para grandes cantidades de datos, ya que no proporciona ninguna forma de realizar ningún procesamiento de transmisión;Además, es posible que el manejo de errores no sea lo suficientemente detallado para sus necesidades.Pero hace que los muchos casos simples sean realmente en realidad simple.

Hay un comando especial en Perl para ello.

open2()

Puede encontrar más información en: http://sunsite.ualberta.ca/Documentation/Misc/perl-5.6.1/lib/IPC/Open2.html

Si no desea incluir paquetes adicionales, puede hacerlo

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

que es lo contrario de lo que sugeriste, pero también debería funcionar.

Siempre lo hago de esta manera si solo espero una única línea de salida o quiero dividir el resultado en algo que no sea una nueva línea:

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

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

Si desea manejar una respuesta de varias líneas, obtenga el resultado como una matriz:

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

foreach ( my $line ) (@lines) {  
    if ( $line =~ /some pattern/ ) {  
        do_something();  
    }  
}  
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top