2012-03-09 55 views
7

我正嘗試從Perl中的管道中讀取非緩衝數據。例如在下面的程序中:從管道中讀取未緩衝的數據在Perl中

open FILE,"-|","iostat -dx 10 5"; 
$old=select FILE; 
$|=1; 
select $old; 
$|=1; 

foreach $i (<FILE>) { 
    print "GOT: $i\n"; 
} 

iostat每隔10秒(五次)吐出數據。你會期望這個程序也這樣做。然而,相反,它似乎掛起了50秒(即10x5),之後它將全部的數據吐出。

我怎樣才能得到任何可用的數據(以無緩衝的方式),而不用等待EOF的所有方式?

P.S.我在Windows下看到了很多這方面的參考資料 - 我在Linux下這樣做。

+4

你應該使用'while'而不是'foreach'。而你的輸出緩衝是不重要的,因爲它是一個輸入句柄而不是輸出句柄。 – tchrist 2012-03-09 17:45:24

+0

使用while和foreach有什麼區別? – Jean 2012-03-12 16:46:22

+0

@alertjean:在'foreach my $ i(){...}'中,文件讀取是在列表上下文中完成的,也就是說,在'foreach'循環中處理行之前讀取整個文件。在'while(my $ i = ){...}'中,讀取是在標量上下文中完成的,也就是說,讀取每行並在while塊中處理每行,然後讀取下一行。 – 2012-03-14 17:22:18

回答

5
#!/usr/bin/env perl 

use strict; 
use warnings; 



open(PIPE, "iostat -dx 10 1 |")  || die "couldn't start pipe: $!"; 

while (my $line = <PIPE>) { 
    print "Got line number $. from pipe: $line"; 
} 

close(PIPE)       || die "couldn't close pipe: $! $?"; 
+1

這個工作,甚至沒有啓用STDOUT自動刷新 – Jean 2012-03-12 16:47:19

+0

這個例子屬於perldoc readline。 – 2017-07-12 02:40:16

1

如果在你的Perl腳本中等待而不是在linux命令中,這應該可以工作。 我不認爲在命令執行完成之前,Linux會將控制權交還給Perl腳本。

#!/usr/bin/perl -w 
my $j=0; 
while($j!=5) 
{ 
    open FILE,"-|","iostat -dx 10 1"; 
    $old=select FILE; 
    $|=1; 
    select $old; 
    $|=1; 

    foreach $i (<FILE>) 
    { 
     print "GOT: $i"; 
    } 
    $j++; 
    sleep(5); 
} 
+6

**設置'$ |'隻影響輸出緩衝。**你不能以這種方式影響其他程序的輸出緩衝。加上什麼是奇怪的開放,而不是隻是開放(PIPEHANDLE,「iostat -dx 10 1 |」)||死「不能啓動管道」;'?我永遠不會記得''| - ''vs'「 - |」'我自己。無論如何,如果'iostat'程序不是通過管道沖洗它的緩衝區,你必須轉向ptys,這是一個真正麻煩但不可行的。 – tchrist 2012-03-09 17:44:42

1

我有下面的代碼對我來說

#!/usr/bin/perl 
use strict; 
use warnings; 
open FILE,"-|","iostat -dx 10 5"; 

while (my $old=<FILE>) 
{ 
    print "GOT: $old\n"; 
} 
+0

爲什麼不打開(FILE,「iostat -dx 10 5 |」)'? – tchrist 2012-03-09 17:41:29

+0

@tchist因爲'打開PIPE','|','iostat','-dx',10,5'或死亡$! – larelogio 2017-09-17 14:53:26

1

的解決方案,到目前爲止並沒有爲我與問候合作努力unbuffering(視窗的ActiveState Perl的5.10)。

根據http://perldoc.perl.org/PerlIO.html,「爲了獲得未緩衝的流,在公開調用中指定無緩衝層(例如:unix):」。

所以

open(PIPE, '-|:unix', 'iostat -dx 10 1') or die "couldn't start pipe: $!"; 

while (my $line = <PIPE>) { 
    print "Got $line"; 
} 

close(PIPE); 

它曾在我的情況。