みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

コンソール出力をテキストに出力する方法(コンソール出力は残しつつ)

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

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

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

【環境】
 Windows2000
 Active Perl 5.8.8

投稿日時 - 2007-11-13 22:45:10

QNo.3515763

困ってます

質問者が選んだベストアンサー

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/File/Tee.pm

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;

投稿日時 - 2007-11-13 23:23:34

補足

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

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

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

投稿日時 - 2007-11-14 20:00:00

お礼

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

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

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

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

投稿日時 - 2007-11-13 23:44:03

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(3)

ANo.3

ん?
手元では 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 20:44:25

補足

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

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

投稿日時 - 2007-11-14 21:12:07

ANo.2

要は「標準エラーと標準出力が同じところに出ればいい」ので,
open(STDERR, ">&STDOUT");
または
open(STDOUT, ">&STDERR");
でなんとかなっちゃったりして.

投稿日時 - 2007-11-14 00:54:09

お礼

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

ファイルハンドルを別のものに置き換える(関連付ける?)方法というのも考えていたのですが、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:09

あなたにオススメの質問