2014-03-03 27 views
3

我有一個perl腳本,讀取輸出(逐行)當來自另一過程管道,做了位處理和噴出出其結果:改變輸入記錄分隔符到 n或 r解析線

#!/bin/bash 
set -e 
set -o pipefail 

RUN.SH ${@} 2>&1 | perl -M"Term::ANSIColor" -wnl -e ' 
m/ERROR/i and print "\e[1;91m", "$_", "\e[0m" 
or print;' 

它的效果很好,除非過程RUN.SH的輸出不以新行結束(\n),而以\r結束!在這種情況下,這個Perl解析器不會打印任何東西,直到下一個\n。我需要更改它,以便它將使用\n\r作爲輸入記錄分隔符。

有什麼想法?

+0

雞蛋裏挑骨頭:你'使用期限:: ANSIColor'但你實際上並不使用* *任期:: ANSIColor。 – ThisSuitIsBlackNot

回答

3

有四種方法可以從文件中讀取:

  • 一個字符一個時間:每次getc
  • 一號線: readline$/ = $terminator;
  • 一次一個塊:readreadline$/ = \$length;
  • 當數據到達時:sysread

getc會的工作,但我會用更高效的sysread

perl -we' 
    sub make_iter { 
     my ($fh) = @_; 

     my $buf = ""; 
     my $eof = 0; 

     return sub { 
     return if $eof; 

     while (1) { 
      return $1 if $buf =~ s/^([^\r\n]*[\r\n])//; 

      my $rv = sysread(STDIN, $buf, 64*1024, length($buf)); 
      if (!$rv) { 
       $eof = 1; 
       die $! if !defined($rv); 
       return $buf if length($buf); 
       return; 
      } 
     } 
     }; 
    } 

    binmode(STDIN); 
    binmode(STDOUT); 
    $| = 1; 

    my $iter = make_iter(\*STDIN); 
    while (my ($line) = $iter->()) { 
     $line = "\e[1;91m" . $line . "\e[0m" if $line =~ /ERROR/i; 
     print($line); 
    } 
' 
0

只需插入替換管段:

... | perl -pe's/\ r/\ n/g'| ...

RUN.SH ${@} 2>&1 | perl -pe 's/\r/\n/g' | perl -M"Term::ANSIColor" -wnl -e ' 
m/ERROR/i and print "\e[1;91m", "$_", "\e[0m" 
or print;' 

測試:

[email protected]:~> echo -e 'a\nb\rc\n' 
a 
c 

[email protected]:~> echo -e 'a\nb\rc\n' | perl -pe 's/\r/\n/g' 
a 
b 
c 
+0

雖然這裏有一個問題!當'JOB.SH'輸出是例如一個定時器(這就是爲什麼它不打印一個新行),我會有許多定時器印在新行上,而不是在同一行上 –

+2

這將仍然阻塞,直到換行收到。 – ikegami

-4

哦,男孩,很多偉大的和不知道的腳本是不正確的。

'$ INPUT_RECORD_SEPARATOR'更改此默認值爲'\ n',您可以將它更改爲您在perl腳本本身中即時需要的內容。

你可以閱讀更多在perl special variables使用Web瀏覽器找到並搜索「INPUT_RECORD_SEPARATOR」

+0

獵物告訴如何將其更改爲「CR或LF」! – ikegami

+0

這不回答這個問題。您可以將'$ /'設置爲'\ n' *或*'\ r',但不能同時設置。 – ThisSuitIsBlackNot

+0

你可以將它設置爲你想要的任何東西「\ n \ n」「啤酒」等。明顯缺乏perl知識的答案,但無論如何。另外我測試了我自己的,我用很少的代碼獲得了相同的結果。 – alexmac