9

STDOUTが同じでない場合にのみ、PerlにSTDERRへの書き込みをお願いします。たとえば、STDOUTとSTDERRの両方が出力をターミナルにリダイレクトする場合、STDERRを出力したくありません。

次の例(outerr.pl)について考えてみます。

#!/usr/bin/perl

use strict;
use warnings;

print STDOUT "Hello standard output!\n";
print STDERR "Hello standard error\n" if ($someMagicalFlag);
exit 0

今これを考えてください(これは私が達成したいことです):

bash $ outerr.pl
Hello standard output!

ただし、ファイルにリダイレクトする場合は、次の情報を取得したいと思います。

bash $ outerr.pl > /dev/null
Hello standard error

逆の場合も同様です。

bash $ outerr.pl 2> /dev/null
Hello standard output!

out / errの両方を同じファイルにリダイレクトすると、outのみが表示されます。

bash $ outerr.pl > foo.txt 2>&1
bash $ cat foo.txt
Hello standard output!

では、OUTとERRが同じ「もの」(記述子?)を指しているかどうかを評価/決定する方法はありますか?

4

2 に答える 2

11

Unixスタイルのシステムでは、次のことができるはずです。

my @stat_err = stat STDERR;
my @stat_out = stat STDOUT;

my $stderr_is_not_stdout = (($stat_err[0] != $stat_out[0]) ||
                            ($stat_err[1] != $stat_out[1]));

ただし、実際のiノード番号がないWindowsでは機能しません。誤検知(そうでない場合は異なると考える)と誤検知(そうでない場合は同じであると考える)の両方を提供します。

于 2013-03-14T19:13:41.473 に答える
4

あなたは-tでそれを(ほとんど)することができます:

-t STDERR

それが端末である場合、および同様にSTDOUTの場合に当てはまります。

それでも、どの端末かはわかりません。同じファイルにリダイレクトすると、両方を取得する可能性があります。

したがって、

-t STDERR && ! (-t STDOUT) || -t STDOUT && !(-t STDERR)

以下

-t STDOUT ^ -t STDERR  # thanks to @mob

あなたは大丈夫だと知っています。

編集:STDERRとSTDOUTの両方が通常のファイルである場合の解決策:

Tom Christiansonは、devフィールドとinoフィールドを統計して比較することを提案しました。これはUNIXで機能しますが、@ cjmが指摘したように、Windowsでは機能しません。

他のプログラムがファイルに書き込まないことを保証できる場合は、WindowsとUNIXの両方で次のことを実行できます。

  1. STDOUTとSTDERRのファイル記述子の位置を確認します。それらが等しくない場合は、それらの1つを>>空でないファイルにリダイレクトしました。
  2. それ以外の場合は、ファイル記述子2に42バイトを書き込みます
  3. ファイル記述子1の終わりを探します。以前より42多い場合は、両方が同じファイルにリダイレクトされる可能性が高くなります。変更されていない場合、ファイルは異なります。変更されたが42までに変更されていない場合、他の誰かがそこに書き込んでいると、すべての賭けが無効になります(ただし、Windowsを使用していないため、statメソッドが機能します)。
于 2013-03-14T18:34:38.603 に答える