2009-09-25 10 views
20

Voglio avere l'output del programma da riga di comando di Windows (ad esempio, powercfg -l) scritto in un file che viene creato utilizzando Perl e quindi leggere il file riga per riga in un ciclo for e assegnarlo a una stringa.Come ottengo l'output di un comando esterno in Perl?

+0

Per favore aggiorna la tua domanda con tutti i dettagli che hai nei commenti alle risposte in modo che le persone possano aiutarti meglio. I messaggi di errore che ricevi e un esempio di ciò su cui stai lavorando ti aiuteranno. –

risposta

20
my $output = qx(powercfg -l); 

## You've got your output loaded into the $output variable. 
## Still want to write it to a file? 
open my $OUTPUT, '>', 'output.txt' or die "Couldn't open output.txt: $!\n"; 
print $OUTPUT $output; 
close $OUTPUT 

## Now you can loop through each line and 
## parse the $line variable to extract the info you are looking for. 
foreach my $line (split /[\r\n]+/, $output) { 
    ## Regular expression magic to grab what you want 
} 
22
system 'powercfg', '-l'; 

è il metodo consigliato. Se non ti dispiace generare una subshell,

system "powercfg -l"; 

funzionerà anche. E se si desidera che i risultati in una stringa:

my $str = `powercfg -l`; 
+0

Risposta migliore del mio – Xetius

+1

Non dimenticare di controllare il valore restituito dalla chiamata di sistema. – Craig

+0

@craig: c'è un modo per controllare il valore restituito E catturare l'output in una stringa? – jimtut

2

Dal momento che l'OP è in esecuzione powercfg, s/he sono probabilmente catturare l'output dello script esterno, in modo s/che probabilmente non troverà questa risposta terribilmente utile . Questo post è principalmente scritto per altre persone che trovano le risposte qui cercando.

Questa risposta descrive diversi modi per avviare il comando che verrà eseguito in background senza bloccare l'ulteriore esecuzione dello script.

Dai uno sguardo allo perlport entry for system. È possibile utilizzare system(1, 'command line to run'); per generare un processo figlio e continuare lo script.

Questo è davvero molto utile, ma c'è un avvertimento serio che è non documentato. Se si avviano più 64 processi in un'unica esecuzione dello script, i tentativi di eseguire programmi aggiuntivi avranno esito negativo.

Ho verificato che questo è il caso di Windows XP e ActivePerl 5.6 e 5.8. Non ho provato questo con Vista o con Stawberry Perl, o con qualsiasi versione di 5.10.

Ecco un uno di linea è possibile utilizzare per verificare la vostra perl per questo problema:

C:\>perl -e "for (1..100) { print qq'\n $_\n-------\n'; system(1, 'echo worked'), sleep 1 } 

Se il problema esiste sul vostro sistema, e si inizierà molti programmi, è possibile utilizzare il modulo Win32::Process da gestire l'avvio della tua applicazione.

Ecco un esempio di utilizzo Win32::Process:

use strict; 
use warnings; 

use Win32::Process; 

if(my $pid = start_foo_bar_baz()) { 
    print "Started with $pid"; 
} 
:w 

sub start_foo_bar_baz { 

    my $process_object; # Call to Create will populate this value. 
    my $command = 'C:/foo/bar/baz.exe'; # FULL PATH to executable. 
    my $command_line = join ' ', 
      'baz', # Name of executable as would appear on command line 
      'arg1', # other args 
      'arg2'; 

    # iflags - controls whether process will inherit parent handles, console, etc. 
    my $inherit_flags = DETACHED_PROCESS; 

    # cflags - Process creation flags. 
    my $creation_flags = NORMAL_PRIORITY_CLASS; 

    # Path of process working directory 
    my $working_directory = 'C:/Foo/Bar'; 

    my $ok = Win32::Process::Create(
     $process_object, 
     $command, 
     $command_line, 
     $inherit_flags, 
     $creation_flags, 
     $working_directory, 
    ); 

    my $pid; 
    if ($ok) { 
     $pid = $wpc->GetProcessID; 
    } 
    else { 
     warn "Unable to create process: " 
      . Win32::FormatMessage(Win32::GetLastError()) 
     ; 
     return; 
    } 

    return $pid; 
} 
1

Prova utilizzando> all'operatore di inoltrare l'output in un file, come:

powercfg -l > output.txt 

E poi output.txt aperto ed elaborarlo.

+0

Ciao, voglio usare Perl in questo .... perché non so come catturare l'output in un file (da creare) e leggere quel file riga per riga e assegnare la linea a una stringa nello script PERL . –

8

Non v'è alcuna necessità di salvare prima l'output del comando in un file:

my $output = `powercfg -l`; 

Vedi qx// in Quote-Like Operators.

Tuttavia, se si desidera salvare prima l'output in un file, quindi è possibile utilizzare:

my $output_file = 'output.txt'; 

system "powercfg -l > $output_file"; 

open my $fh, '<', $output_file 
    or die "Cannot open '$output_file' for reading: $!"; 

while (my $line = <$fh>) { 
    # process lines 
} 

close $fh; 

Vedi perldoc -f system.

2

Per espandere sulla risposta eccellente di Sinan e di rispondere in modo più esplicito alla tua domanda:

NOTA: backticks `` dicono Perl per eseguire un comando e recuperare il suo output:

#!/usr/bin/perl -w 
use strict; 


my @output = `powercfg -l`; 
chomp(@output); # removes newlines 

my $linecounter = 0;  
my $combined_line; 

foreach my $line(@output){ 
    print $linecounter++.")"; 
    print $line."\n"; #prints line by line 

    $combined_line .= $line; # build a single string with all lines 
    # The line above is the same as writing: 
    # $combined_line = $combined_line.$line; 
} 

print "\n"; 
print "This is all on one line:\n"; 
print ">".$combined_line."<"; 

L'output (sul mio sistema):

0) 
1)Existing Power Schemes (* Active) 
2)----------------------------------- 
3)Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced) * 
4)Power Scheme GUID: 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c (High performance) 
5)Power Scheme GUID: a1841308-3541-4fab-bc81-f71556f20b4a (Power saver) 

This is all on one line: 
>Existing Power Schemes (* Active)-----------------------------------Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced) *Power Scheme GUID: 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c (High performance)Power Scheme GUID: a1841308-3541-4fab-bc81-f71556f20b4a (Power saver)< 

Perl rende tutto più semplice!

19

Hai già delle buone risposte. Inoltre, se si desidera elaborare l'output di un comando e non è necessario inviare tale output direttamente a un file, è possibile stabilire una pipe tra il comando e lo script Perl.

use strict; 
use warnings; 

open(my $fh, '-|', 'powercfg -l') or die $!; 
while (my $line = <$fh>) { 
    # Do stuff with each $line. 
} 
+3

Non è necessario eseguire il test definito durante la lettura da un handle di file in un'istruzione while. Vedi l'output di 'perl -MO = Deparse -e" stampa mentre <> "' –

+0

@Sinan Grazie mille. Non avevo familiarità con '-MO = Deparse'. Molto utile. – FMc

+0

Questo è bello in quanto il mio $ var = 'comando' può sfuggire di mano se il comando capita di produrre una quantità di output oltraggiosa e si inizia lo scambio. Non tipico ma succede. –

Problemi correlati