2012-09-10 49 views
6

有一個文件:Perl中,禁用緩存輸入端

:~$ cat fff 
qwerty 
asdf 
qwerty 
zxcvb 

有一個腳本:

:~$ cat 1.pl 
#!/usr/bin/perl 
print <STDIN> 

命令按預期工作:

:~$ cat fff | perl -e 'system("./1.pl")' 
qwerty 
asdf 
qwerty 
zxcvb 

但是該命令將不按預期工作:第一個<STDIN>讀取所有數據,而不是一行。如何禁用緩衝<STDIN>?

:~$ cat fff | perl -e '$_ = <STDIN>; system("./1.pl")' 
:~$ 
+0

你確定'cat fff | perl -e'系統(「./ 1.pl」)''打印內容?對我來說只有'貓fff | perl 1.pl'確實。 – tuxuday

回答

6

這裏有兩種Perl的過程 - 即分配$_ = <STDIN>並調用system第一,而且確實print <STDIN>

雖然只有流的第一行是由該第一處理讀入$_第二,幕後Perl已經用數據填充緩衝區,並將流留空

這是什麼目的?我想到的唯一的辦法做你問什麼是閱讀將文件放入第一處理數組的所有,然後取出第一線,並在管道發送剩下的第二個腳本

所有這一切似乎是不必要的,而且我相信有,如果你將說明根本問題

更新

既然你說你都知道的緩衝問題,要做到這一點的方式是一個更好的方法使用sysread,它將從較低級別的管道讀取並避免緩衝

像這樣將工作

cat fff | perl -e 'while (sysread(STDIN, $c, 1)) {$_ .= $c; last if $c eq "\n"} system("./1.pl")' 

但我不喜歡推薦它,你在做什麼,似乎非常錯誤的,我希望你能解釋一下你的真正目標

+0

您可以閱讀一行「tell」,重新打開文件和「seek」。 – choroba

+0

@choroba:是的,但不是來自管道 – Borodin

+0

'$ cat fff | perl -ne'print除非$。 == 1'| 。/ 1.pl'將成爲刪除第一行的優雅解決方案。 – amon

0

我最近有解析每個大約6千兆字節的幾個日誌文件。緩衝是一個問題,因爲當我將STDIN分配給一個數組時,Perl會愉快地嘗試將這6千兆字節讀入內存......但是,我根本沒有可用的系統資源來完成這項工作。我提出了下面的解決方法,它只需逐行讀取文件,從而避免大量內存黑洞緩衝渦旋,否則這些渦旋會佔用我所有的系統資源。

注意:該腳本所做的全部工作是將6 GB的文件拆分爲幾個較小的文件(其大小由每個輸出文件中包含的行數決定)。有趣的是while循環以及從日誌文件到變量的單行分配。循環將遍歷整個文件讀取一行,對其執行某些操作,然後重複。結果,沒有大規模的緩衝...我保持整個腳本完整,只是爲了顯示一個工作的例子...

#!/usr/bin/perl -w 
BEGIN{$ENV{'POSIXLY_CORRECT'} = 1;} 
use v5.14; 
use Getopt::Long qw(:config no_ignore_case); 

my $input = ''; 
my $output = ''; 
my $lines = 0; 
GetOptions('i=s' => \$input, 'o=s' => \$output, 'l=i' => \$lines); 

open FI, '<', $input; 

my $count = 0; 
my $count_file = 1; 
while($count < $lines){ 
    my $line = <FI>; #assign a single line of input to a variable 
    last unless defined($line); 
    open FO, '>>', "$output\_$count_file\.log"; 
    print FO $line; 
    $count++; 
    if($count == $lines){ 
     $count=0; 
     $count_file++; 
    } 
} 
print " done\n"; 

腳本調用等在命令行上:

(腳本的名稱)-i(輸入文件)-O(輸出文件)-1-(輸出文件(即行數的大小)

即使它不完全符合你的要求,我希望它能給你一些想法。:)