2008-09-16 134 views
3

在Perl腳本中間,有一個我想要執行的系統命令。我有一個字符串,其中包含需要輸入到stdin的數據(該命令只接受來自stdin的輸入),並且我需要捕獲寫入stdout的輸出。我已經看過在Perl中執行系統命令的各種方法,並且open函數似乎是我需要的,除了它看起來像我只能捕獲stdin或stdout,而不是兩者。如何從Perl腳本捕獲系統命令的stdin和stdout?

目前,似乎我最好的解決方案是使用open,將stdout重定向到臨時文件,並在命令完成後從文件中讀取。有更好的解決方案嗎?

回答

3

腳本頂部的某處,包括行

use IPC::Open2; 

這將包括必要的模塊,默認情況下通常安裝在大多數Perl發行版中。 (如果你沒有的話,你可以使用CPAN安裝。)然後,而不是開放的,電話:

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

您可以通過它發送到$ CMD_IN將數據發送到您的命令,然後讀你的命令的通過從$ cmd_out讀取輸出。

如果您還希望能夠讀取該命令的stderr流,則可以改爲使用IPC :: Open3模塊。

+1

對於閱讀此內容的任何人,您應該確保並且不要像本示例那樣使用裸號文件句柄。看到這個文檔:http://www.perlfoundation.org/perl5/index.cgi?bareword_uppercase_filehandles – 2008-09-17 03:14:05

0

我總是做這樣子的話,我只希望輸出的單行或希望的結果比上一個新行以外的東西分裂:

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

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

如果你想對付多行反應,得到的結果作爲數組:

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

foreach (my $line) (@lines) { 
    if ($line =~ /some pattern/) { 
     do_something(); 
    } 
} 
+0

我看不到你的例子在哪裏處理STDIN。 – 2010-11-08 18:52:41

3

perlipc documentation涵蓋了許多方法,你可以做到這一點,包括IPC :: Open2和IPC :: Open3。

6

IPC :: Open2/3都很好,但我發現,通常都是我真正需要的是IPC::Run3,它以最簡單的處理簡單的情況非常好:

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

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

的文檔比較IPC: :Run3到其他選擇。即使您不決定使用它,也值得閱讀。

0

如果你不希望包括額外的軟件包,你可以做

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

這是你的建議,相反,還應該工作。

2

我最近發現的一個非常簡單的方法是IPC::Filter模塊。它可以讓你做的工作非常直觀:

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

注意它是如何,如果你傳遞一個列表,而無需通過shell去調用你的命令。它還爲處理常見實用程序的錯誤做了合理的工作。 (在失敗時,它使用來自STDERR的文本作爲其錯誤消息;在成功時,STDERR僅被丟棄。)

當然,由於它不提供任何方式來執行任何操作,因此它不適合大量數據流處理;此外,錯誤處理可能不夠精細,無法滿足您的需求。但它使得很多簡單的案例真的很簡單真的