2

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");

stderr をリダイレクトして stdout で処理できるようにしようとしていますが、機能しません。

解決策は、Windowsで機能する必要があります。

4

1 に答える 1

3

引数のシェル リダイレクトは、次の場合に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";
}

出力は

標準誤差
[標準出力]を得た

からの標準出力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";
}

今、出力は

[標準エラー] を取得しました
[標準出力]を得た
于 2012-05-14T14:24:07.723 に答える