2009-09-25 115 views
20

我想輸出寫入使用Perl創建的文件的Windows命令行程序(例如,powercfg -l),然後在for循環中逐行讀取文件並將其分配給字符串。如何在Perl中獲得外部命令的輸出?

+0

請更新您的問題,並在答案的評論中提供所有詳細信息,以便人們可以更好地爲您提供幫助。您收到的錯誤消息以及您正在使用的示例將有所幫助。 – 2009-09-26 17:14:03

回答

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

是推薦的方法。如果你不介意產生子殼,

system "powercfg -l"; 

也可以。如果你想在一個字符串的結果:

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

比我的回答更好 – Xetius 2009-09-16 14:35:24

+1

不要忘記檢查系統調用的返回值。 – Craig 2009-09-16 14:36:30

+0

@craig:有沒有辦法檢查返回值並捕獲字符串中的輸出? – jimtut 2009-09-16 16:15:14

2

由於OP運行powercfg,他/她可能正在捕捉外部腳本的輸出中,那麼他/她可能會找不到這個答案非常有用。這篇文章主要是爲通過搜索找到答案的其他人撰寫的。

此答案描述了幾種啓動將在後臺運行的命令的方法,而不會阻止腳本的進一步執行。

看看perlport entry for system。你可以使用system(1, 'command line to run');產生一個子進程並繼續你的腳本。

這真的很方便,但有一個嚴重的警告是不是記錄。如果在腳本的一次執行中啓動更多64個進程,則嘗試運行其他程序將失敗。

我已經驗證這是Windows XP和ActivePerl 5.6和5.8的情況。我還沒有用Vista或Stawberry Perl或5.10的任何版本進行測試。

這裏有一個襯墊,你可以用它來測試你的Perl對於這個問題:

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

如果你的系統中存在的問題,你會開始很多程序,你可以使用Win32::Process模塊管理你的程序啓動。

下面是一個使用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

嘗試使用>運算符輸出轉發到一個文件,如:

powercfg -l > output.txt 

,然後打開output.txt中,並對其進行處理。

+0

您好我想在此....中使用Perl,因爲我不知道如何捕獲文件中的輸出(要創建)並逐行讀取該文件並將該行分配給PERL腳本中的字符串。 – 2009-09-25 14:16:30

8

沒有必要先保存命令的輸出文件:

my $output = `powercfg -l`; 

qx//Quote-Like Operators

但是,如果你想先保存在一個文件輸出,那麼你可以使用:

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; 

perldoc -f system

2

要擴大思南的出色答卷,並更明確地回答你的問題:

注:反引號``告訴Perl來執行命令和檢索其輸出:

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

你的輸出(在我的系統上)應該是:

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讓它變得簡單!

19

你已經有了一些很好的答案。另外,如果您只想處理命令的輸出,而不需要直接將該輸出發送到文件,則可以在命令和Perl腳本之間建立管道。

use strict; 
use warnings; 

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

從while語句中的文件句柄讀取時,不需要定義的測試。查看'perl -MO = Deparse -e「的輸出結果,同時<>」' – 2009-09-25 15:23:08

+0

@Sinan非常感謝。我不熟悉'-MO = Deparse'。很有用。 – FMc 2009-09-25 15:56:14

+0

這很好,因爲如果命令恰好會產生大量的輸出並且您開始交換,那麼我的$ var ='command'可能會失控。不典型,但它發生。 – 2014-12-17 18:33:35

相關問題