2009-09-25 5 views
20

Je souhaite que la sortie du programme de ligne de commande Windows (disons, powercfg -l) soit écrite dans un fichier créé à l'aide de Perl, puis lise le fichier ligne par ligne dans une boucle for et l'affecte à une chaîne.Comment obtenir la sortie d'une commande externe en Perl?

+0

S'il vous plaît mettre à jour votre question avec tous les détails que vous avez dans les commentaires aux réponses afin que les gens peuvent vous aider à mieux. Les messages d'erreur que vous obtenez et un exemple de ce que vous utilisez vous aideront. –

Répondre

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'; 

est la méthode recommandée. Si cela ne vous dérange pas de pondre un sous-shell,

system "powercfg -l"; 

fonctionnera aussi. Et si vous voulez que les résultats dans une chaîne:

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

Meilleure réponse que la mienne – Xetius

+1

N'oubliez pas de vérifier la valeur de retour de l'appel système. – Craig

+0

@craig: Existe-t-il un moyen de vérifier la valeur de retour ET de capturer la sortie dans une chaîne? – jimtut

2

Depuis l'OP est en cours d'exécution powercfg, il/capturons probablement le ouput du script externe, donc il/elle ne sera probablement pas trouvé cette réponse terriblement utile . Ce post est principalement écrit pour d'autres personnes qui trouvent les réponses ici en cherchant.

Cette réponse décrit plusieurs façons de démarrer une commande qui s'exécutera en arrière-plan sans bloquer l'exécution de votre script.

Jetez un oeil à la perlport entry for system. Vous pouvez utiliser system(1, 'command line to run'); pour générer un processus enfant et continuer votre script.

Ceci est vraiment très pratique, mais il y a un avertissement sérieux qui est pas documenté. Si vous démarrez plus de 64 processus en une seule exécution du script, vos tentatives d'exécution de programmes supplémentaires échoueront.

J'ai vérifié que c'était le cas avec Windows XP et ActivePerl 5.6 et 5.8. Je n'ai pas testé cela avec Vista ou avec Stawberry Perl, ou n'importe quelle version de 5.10.

est ici une seule ligne vous pouvez utiliser pour tester votre perl pour ce problème:

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

Si le problème existe sur votre système, et vous serez démarrage de plusieurs programmes, vous pouvez utiliser le module Win32::Process pour gérer le démarrage de votre application.

Voici un exemple d'utilisation 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

Essayez d'utiliser> opérateur pour transférer la sortie vers un fichier, comme:

powercfg -l > output.txt 

Et puis sortie.txt ouvert et traiter.

+0

Salut je veux utiliser Perl dans ce .... car je ne sais pas comment capturer la sortie dans un fichier (à créer) et lire ce fichier ligne par ligne et l'attribution de la ligne à une chaîne dans le script PERL . –

8

Il n'y a pas besoin d'enregistrer d'abord la sortie de la commande dans un fichier:

my $output = `powercfg -l`; 

Voir qx// dans Quote-Like Operators.

Cependant, si vous ne voulez d'abord enregistrer la sortie dans un fichier, vous pouvez utiliser:

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; 

Voir perldoc -f system.

2

Pour développer une excellente réponse et de répondre plus explicitement votre question de Sinan:

REMARQUE: les apostrophes inverses `` dire Perl pour exécuter une commande et récupérer sa sortie:

#!/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."<"; 

Votre sortie (sur mon système) serait:

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 le rend facile!

19

Vous avez déjà de bonnes réponses. De plus, si vous voulez simplement traiter la sortie d'une commande et n'avez pas besoin d'envoyer cette sortie directement à un fichier, vous pouvez établir un canal entre la commande et votre script Perl.

use strict; 
use warnings; 

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

Le test défini n'est pas nécessaire lors de la lecture d'un descripteur de fichier dans une instruction while. Voir la sortie de 'perl -MO = Deparse -e" imprimer alors que <> "' –

+0

@Sinan Merci beaucoup. Je ne connaissais pas '-MO = Deparse'. Très utile. – FMc

+0

C'est sympa en ce que mon $ var = 'commande' peut devenir incontrôlable si la commande produit une quantité scandaleuse de sortie et que vous commencez à échanger. Pas typique mais ça arrive. –

Questions connexes