プロが教えるわが家の防犯対策術!

【質問】
 Perl内部で実行される実行ファイル(.exe)のコンソール出力(STDOUT,STDERR)をテキストファイルに出力したい。(Perlのコンソール出力も含む。) ※コンソール出力は残しつつ。

(コマンドプロンプトの)パイプとリダイレクトを使用して上手くいくかと思ったのですが、標準出力と標準エラーとでは標準エラーが先に出力されてしまい、本来出力される順番で出力されない。(標準出力はバッファにたまるため??)

何かいい方法はありませんでしょうか?

【環境】
 Windows2000
 Active Perl 5.8.8

A 回答 (3件)

CPANモジュールの File::TeeとかIO::Teeを使うというのはどうでしょうか?



File::Tee - replicate data sent to a Perl stream - search.cpan.org
http://search.cpan.org/~salva/File-Tee-0.03/lib/ …

use File::Tee qw(tee);

# simple usage:
tee(STDOUT, '>', 'stdout.txt');

print "hello world\n";

IO::Tee - Multiplex output to multiple output handles - search.cpan.org
http://search.cpan.org/~kenshan/IO-Tee-0.64/Tee.pm

use IO::Tee;
use IO::File;

my $tee = new IO::Tee(\*STDOUT,
new IO::File(">tt1.out"), ">tt2.out");

print join(' ', $tee->handles), "\n";

for (1..10) { print $tee $_, "\n" }
for (1..10) { $tee->print($_, "\n") }
$tee->flush;

この回答への補足

調べてみたのですが、File::TeeモジュールはWindowsでは使用できないみたいですね。

別の方法を検討してみます。

ありがとうございました。

補足日時:2007/11/14 20:00
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
ただ、勉強不足のため間違っていたら申し訳ないのですが、Teeモジュールを使用することで、二つ以上のハンドルに同時出力しているのだと思います。しかし、これではPerl内部で実行される実行ファイルのコンソール出力までは出力先を変更できないのではないでしょうか?

説明がわかりにくかったかと思いますので、例を記述します。以下のprint文とsystem()で出力される標準出力と標準エラーをテキストファイルに取得したいのです。(コンソール出力は残したままで)
※下の例ではエラーは発生しませんが。。

(例)
 $cmd = "dir"; # 実行ファイルの代わり。
print"カレントディレクトリ内のファイルを表示 開始\n";
system($cmd); # 実際には.exeファイル
print"カレントディレクトリ内のファイルを表示 終了\n";

説明不足で申し訳ございませんでした。どなたかご教授いただけると助かります。

お礼日時:2007/11/13 23:44

ん?


手元では Windows XP + ActivePerl 5.8.6 だけど, なんとなく
-------------------- ここから
open(STDERR, ">&STDOUT");
print "foo\n";
print STDERR "bar\n";
system('echo "foo foo"');
system('echo "bar bar" 1>&2');
-------------------- ここまで
でうまくいっている (system 内の echo も含めて全て標準出力に出ている) 感じなんですけど....

この回答への補足

はい、コンソールには出力するんですが、テキストファイルにも同時に出力したいのです。

説明下手で申し訳ないです。

補足日時:2007/11/14 21:12
    • good
    • 0

要は「標準エラーと標準出力が同じところに出ればいい」ので,


open(STDERR, ">&STDOUT");
または
open(STDOUT, ">&STDERR");
でなんとかなっちゃったりして.
    • good
    • 0
この回答へのお礼

返事が遅くなり申し訳ございません。および意見をいただきありがとうございます。

ファイルハンドルを別のものに置き換える(関連付ける?)方法というのも考えていたのですが、system()などには反映されない模様。
sakusaker7さんに教えていただいたIO::Teeモジュールを使用して以下のようにしてみた。
#-----------------------------------------------------------
(sample)
use IO::Tee;
my $tee = IO::Tee->new(\*STDOUT,">stdout.txt");
select(*$tee); # print文のデフォルトハンドルに設定

$cmd = "dir"; # 実行ファイルの代わり。
print"カレントディレクトリ内のファイルを表\示 開始\n";
system($cmd); # 実際には.exeファイル
print"カレントディレクトリ内のファイルを表\示 終了\n";
#-----------------------------------------------------------

すると。。print文の内容はコンソール・テキスト両方に出力されるのにsystem()の出力はコンソールにしか出力されない。

うーむ。。わかる方、おりましたらお教えください。

ただ、私も勉強不足が身に染みたので、しばらくしたら質問を閉めさせていただき、出直してきます。

回答をいただけた方、ありがとうございました。

お礼日時:2007/11/14 20:32

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!