2009-09-25 9 views
20

Chcę, aby wyjściowy program wiersza polecenia systemu Windows (na przykład powercfg -l) został zapisany w pliku, który jest tworzony za pomocą Perla, a następnie odczytywany wiersz po wierszu w pętli for i przypisywany do łańcucha.Jak uzyskać dane wyjściowe polecenia zewnętrznego w Perlu?

+0

Proszę zaktualizować swoje pytanie ze wszystkimi szczegółami, które masz w komentarzach, tak aby ludzie mogli ci lepiej pomóc. Otrzymujesz komunikaty o błędach i pomaga Ci przykład tego, z czym pracujesz. –

Odpowiedz

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

to zalecany sposób. Jeśli nie masz nic przeciwko spawaniu podpowłoki, będzie działać również:

system "powercfg -l"; 
A jeśli chcesz wyniki w ciąg znaków:

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

Lepsza odpowiedź niż moja – Xetius

+1

Nie zapomnij sprawdzić zwracanej wartości z wywołania systemowego. – Craig

+0

@craig: Czy istnieje sposób sprawdzenia wartości zwracanej ORAZ przechwycenia wyniku w łańcuchu? – jimtut

2

Ponieważ OP działa powercfg, on/ona prawdopodobnie uchwycenie Ouput skryptu zewnętrznego, tak on/ona prawdopodobnie nie znajdzie tę odpowiedź strasznie użyteczne . Ten post jest przede wszystkim napisany dla innych osób, które znajdują odpowiedzi tutaj, szukając.

Ta odpowiedź opisuje kilka sposobów uruchamiania polecenia, które będą działać w tle bez blokowania dalszego wykonywania skryptu.

Spójrz na perlport entry for system. Możesz użyć system(1, 'command line to run');, aby odrodzić proces potomny i kontynuować skrypt.

Jest to bardzo przydatne, ale jest jedno poważne zastrzeżenie, które zostało udokumentowane jako , a nie. Jeśli w jednym uruchomieniu skryptu uruchomisz więcej 64 procesów, próba uruchomienia dodatkowych programów zakończy się niepowodzeniem.

Sprawdziłem, czy tak jest w przypadku Windows XP i ActivePerl 5.6 i 5.8. Nie testowałem tego z Vistą ani ze Stawberry Perl, ani żadną wersją 5.10.

Oto jeden liniowej można użyć do testowania Perl dla tego problemu:

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

Jeśli problem istnieje w systemie, a będziesz począwszy wiele programów, można użyć modułu Win32::Process zarządzać uruchomienie aplikacji.

Oto przykład użycia 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

> Spróbuj użyć operatora do przekazania wyjście do pliku, jak:

powercfg -l > output.txt 

a następnie otwórz Output.txt i przetwarza je.

+0

Witam Chcę użyć Perla w tym .... ponieważ nie wiem jak przechwycić dane wyjściowe w pliku (który ma zostać utworzony) i czytać ten plik wiersz po linii i przypisywać linię do napisu w skrypcie PERL . –

8

Nie ma potrzeby, aby najpierw zapisać dane wyjściowe polecenia w pliku:

my $output = `powercfg -l`; 

Zobacz qx// w Quote-Like Operators.

Jednakże, jeśli chcesz najpierw zapisać dane wyjściowe w pliku, a następnie można użyć:

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; 

Zobacz perldoc -f system.

2

Aby rozwinąć na doskonałą odpowiedź Sinan i bardziej jednoznacznie odpowiedzieć na pytanie:

UWAGA: backticks `powiedzieć Perl, aby wykonać polecenie i odzyskać swoją moc:

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

swoje wyjście (w moim systemie) będzie:

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 ułatwia!

19

Masz już dobre odpowiedzi. Ponadto, jeśli chcesz przetworzyć dane wyjściowe polecenia i nie musisz wysyłać tych wyników bezpośrednio do pliku, możesz ustanowić potok między poleceniem a skryptem Perla.

use strict; 
use warnings; 

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

Nie ma potrzeby zdefiniowanego testu podczas odczytu z uchwytu pliku w instrukcji while. Zobacz wynik wydruku 'perl -MO = Deparse -e" podczas gdy <> "' –

+0

@Sinan Wielkie dzięki. Nie znałem '-MO = Deparse'. Bardzo przydatne. – FMc

+0

To jest miłe, ponieważ moje polecenie $ var = 'command' może wymknąć się spod kontroli, jeśli polecenie wygeneruje ogromną ilość danych wyjściowych i zaczniesz się zamieniać. Nietypowe, ale się zdarza. –

Powiązane problemy