Come posso catturare stdin e stdout di comando del sistema da uno script Perl?

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

  •  09-06-2019
  •  | 
  •  

Domanda

Nel mezzo di uno script Perl, c'è un sistema di comando che si vuole eseguire.Ho una stringa che contiene i dati che ha bisogno di essere alimentato in stdin (il solo comando accetta input da stdin), e ho bisogno di catturare l'output scritto su stdout.Ho guardato i vari metodi di esecuzione di comandi di sistema in Perl, e il open funzione sembra essere quello di cui ho bisogno, tranne che mi sembra in grado di catturare solo stdin o stdout, non entrambi.

Al momento, sembra che la mia soluzione migliore è utilizzare open, reindirizzare stdout in un file temporaneo, e leggere il file dopo il comando termina.C'è una soluzione migliore?

È stato utile?

Soluzione

Penso che si desidera dare un'occhiata a IPC::Aperto2

Altri suggerimenti

IPC::Aperto2/3 sono belle, ma ho scoperto che di solito tutto quello che ho davvero bisogno è IPC::Run3, che gestisce i casi semplici molto bene con un minimo di complessità:

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

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

La documentazione confronta IPC::Run3 ad altre alternative.Vale la pena di una lettura, anche se non si decide di usarlo.

Il perlipc documentazione copre molti modi che si può fare questo, tra IPC::Aperto2 e IPC::Open3.

Da qualche parte in alto del tuo script, inserire la linea

use IPC::Open2;

Che include il modulo necessario, di solito installato con più Perl distribuzioni per impostazione predefinita.(Se non lo avete, potete installarlo tramite CPAN.) Quindi, invece di aprire, chiamata:

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

È possibile inviare i dati al comando da inviare è di $cmd_in e quindi leggere il tuo output del comando, la lettura di $cmd_out.

Se anche voi volete essere in grado di leggere il comando del flusso stderr, è possibile utilizzare l'IPC::Open3 modulo, invece.

IPC::Open3 sarebbe probabilmente fare quello che vuoi.È in grado di catturare STDERR e STDOUT.

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

Un modo molto semplice per fare ciò che ho trovato di recente è il IPC::Filtro modulo.Esso consente di fare il lavoro estremamente intuitivo:

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

Nota come richiamare il comando senza passare attraverso la shell se si passa un elenco.Lo fa anche un buon lavoro di gestione degli errori per comune utilità.(In caso di errore, si dies, utilizzando il testo da STDERR come messaggio di errore;in caso di successo, STDERR è appena scartato.)

Naturalmente, non è adatto per grandi quantità di dati in quanto non consente in alcun modo di fare streaming di elaborazione;inoltre, la gestione dell'errore potrebbe non essere granulare sufficiente per le vostre esigenze.Ma si rende molti casi più semplici, davvero davvero semplice.

C'è una speciale perl comando per

open2()

Ulteriori informazioni possono essere trovate su: http://sunsite.ualberta.ca/Documentation/Misc/perl-5.6.1/lib/IPC/Open2.html

Se non si desidera includere pacchetti extra, si può solo fare

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

che è il contrario di quello che hai suggerito, ma dovrebbe funzionare anche.

Ho sempre farlo in questo modo se io sono solo in attesa di una singola linea di produzione, o desidera dividere il risultato su qualcosa di diverso da un "a capo":

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

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

Se si vuole affrontare con un multi-linea di risposta, di ottenere il risultato in un array:

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

foreach ( my $line ) (@lines) {  
    if ( $line =~ /some pattern/ ) {  
        do_something();  
    }  
}  
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top