2012-05-14 46 views
2

我想在perl中運行一個外部命令並過濾一些行。 我不知道如何過濾到stderr的行。我有以下代碼現在:Perl合併窗口中的輸出和stderr和過濾行

#!/usr/bin/env perl 

use File::Spec; 
#open STDERR, '>', File::Spec->devnull() or die "could not open STDERR: $!\n"; 

open(FILEHANDLE, '-|', 'Mycmd') or die "Cannot fork: $!\n"; 
open(STDERR, ">&FILEHANDLE"); 

while(defined(my $line = <FILEHANDLE>)) { 
    chomp($line); 
    if($line =~ m/text1/ or 
    $line =~ m/text2/ or 
    $line =~ m/text3/ 
) { 
    # do nothing 
    } 
    else { 
    print "$line\n"; 
    } 
} 
close FILEHANDLE or die "child error: $!\n"; 

open(STDERR, ">&FILEHANDLE"); 

是我嘗試重定向標準錯誤能夠與標準輸出來處理它,但它不工作。

該解決方案將不得不在Windows中工作。

+1

你關閉'STDERR'第一?我不認爲你可以打開已經打開的「FH」。 –

回答

3

一個shell在參數重定向到open可以幫助在這裏:

open(FILEHANDLE, 'Mycmd 2>&1 |') or die "Cannot fork: $!\n"; 

現在FILEHANDLE會看到兩個標準輸出和從Mycmd標準錯誤的每一行。

要使用多重參數open重定向輸出,您必須更加慎重。說Mycmd

#! /usr/bin/env perl 
print "standard output\n"; 
warn "standard error\n"; 

開幕"-|"只給我們的標準輸出,因此,如果我們運行

#! /usr/bin/env perl 

use strict; 
use warnings; 

use 5.10.0; 

my $pid = open my $fh, "-|", "Mycmd" // die "$0: fork: $!"; 

while (defined(my $line = <$fh>)) { 
    chomp $line; 
    print "got [$line]\n"; 
} 

輸出是

standard error 
got [standard output]

注意,從Mycmd標準輸出通過傳遞驅動程序但不是其標準錯誤。爲了得到兩者,你必須模仿外殼’的重定向。

#! /usr/bin/env perl 

use strict; 
use warnings; 

use 5.10.0; 

my $pid = open my $fh, "-|" // die "$0: fork: $!"; 

if ($pid == 0) { 
    open STDERR, ">&STDOUT" or die "$0: dup: $!"; 
    exec "Mycmd"   or die "$0: exec: $!"; 
} 

while (defined(my $line = <$fh>)) { 
    chomp $line; 
    print "got [$line]\n"; 
} 

現在輸出

got [standard error] 
got [standard output]
+0

謝謝,我不知道這種重定向也可以在windows中工作,我熟悉bash中的這些重定向。 – skeept

+0

@skeept不客氣!我很高興它有幫助,並查看自己執行重定向的更新答案,以便您可以繞過shell的愚蠢參數解析。 –