2009-03-17 16 views
2

PerlのSTDOUTからどのようにunaliasするのですか?私はこれを実行すると

open FP, ">xyz"; 

my $file = *FP; 

printf $file "first\n"; 

$file = *STDOUT; 

printf $file "second\n"; 

open $file, ">abc"; 

print $file "third\n"; 

print STDOUT "fourth\n"; 

print FP "fifth\n"; 

を "第4" の印刷ではなく、 "ABC" に、STDOUTには行きません。

STDOUTは、期待どおりに動作するFPとは異なります。

私は間違っていますか?私は何を理解していないのですか?

+0

まず、最初の2つのprintf()がprint()でないのはなぜですか?あなたのプログラムで何らかの理由で問題があるのですか、それとも普通のprint()ですか? –

+0

これは単なるコード例ですが、open()(およびclose()!)呼び出しの戻り値を常にチェックすることを忘れないでください。彼らが成功すると仮定しないでください。 –

+0

'$ file = undef;'、 'open $ファイルの前に、"> abc ";'が働いていました。 –

答えて

11

まずは、まず「オープン」を誤って使用しています。

open my $fp , '>', 'xyz' ; 

は推奨構文です。

あなたが持っている裸のFPは、レキシカルではないので、強くお勧めします。

第2に、新しいものとしてファイルポインタを再オープンしています。これはあまり良い習慣ではありません、それは問題ではありませんが、それは単なる悪い考えです。ファイルポインタを閉じるか、(lexicalを介して)スコープを使い果たすようにしてください。

第3に、 '* STDOUT'は参照です。あなたがこれを行うとき

my $fh = *STDOUT; 
print "$fh\n"; #prints '*main::STDOUT'; 

ので:あなたは

open *STDOUT, '>abc'; 

をやっている

open $fh, '>abc'; 

、あなたは直後

print "$fh\n"; 

をすれば、あなたはまだプリントを、それを注意します*main::STDOUT;これを片付ける

いくつかの興味深いコードスニペット:

my $fh = *STDOUT; 
open $fh, '<', "foo.txt"; 
print $fh "hello"; 
# Filehandle STDOUT opened only for input at (eval 288) line 6. 

my $fh = *STDIN; 
open $fh, '<', "foo.txt"; 
print <>; 
# contents of foo.txt here 

ここで開い使用することをお勧めの方法があります:あなたが近くに省略した場合、ファイルはできるだけ早く閉鎖されること

sub foo { 
    my $fh; 
    open $fh , '<', 'file.txt' or Carp::croak('Cannot Open File.txt'); 
    # do stuff with $fh; 
    close $fh or Carp::carp('Something annoying in close :S '); 
} 

注意$ fhは可視性から外れます。

+0

これは非常に正確に答えるので、私の答えを削除しました。良い説明、ケント。 – Frakkle

+0

3-arg open *は、2-arg openの代わりのドロップではありません。 openプラグマまたは-Cスイッチによって提供されるデフォルトのレイヤーを適用できるようにする場合は、このオプションを使用しないでください。 – ysth

+0

-Cは5.10ではもう動作しません。代わりに明示的なエンコーディングを使用する必要があります。 –

1

$ file、 "> abc"を実行すると、基本的にはSTDOUTのファイル記述子が動作しています。このファイル記述子は別のターゲットに再オープンしました。つまり、両方のエイリアスは、参照するために使用されたエイリアスに関係なく、再利用されている単一の基本リソース上で動作します。そのとき、が開かれます。

4

復元できるようにSTDOUTを保存する必要があります。これはopenのための...はperldocからです:

ここ

は、保存したスクリプトでリダイレクトして、様々な方法を使用してSTDOUTとSTDERRを復元します:

#!/usr/bin/perl 
open my $oldout, ">&STDOUT"  or die "Can't dup STDOUT: $!"; 
open OLDERR,  ">&", \*STDERR or die "Can't dup STDERR: $!"; 

open STDOUT, '>', "foo.out" or die "Can't redirect STDOUT: $!"; 
open STDERR, ">&STDOUT"  or die "Can't dup STDOUT: $!"; 

select STDERR; $| = 1; # make unbuffered 
select STDOUT; $| = 1; # make unbuffered 

print STDOUT "stdout 1\n"; # this works for 
print STDERR "stderr 1\n"; # subprocesses too 

open STDOUT, ">&", $oldout or die "Can't dup \$oldout: $!"; 
open STDERR, ">&OLDERR" or die "Can't dup OLDERR: $!"; 

print STDOUT "stdout 2\n"; 
print STDERR "stderr 2\n"; 

は「か死ぬか」の部分の表情を持っています。あなたは常にエラーのためのオープンをテストする必要があります...

6

あなたがしようとしていることを理解していれば、selectを使いたいと思います。ファイルハンドルを簡単に切り替えることができます。より現代的なオープン形式(3つの引数、字句ファイルハンドル、エラーチェック)も使用する必要があります。 perldoc perlopentutを参照してください。

#!/usr/bin/env perl 
use strict; 
use warnings; 

open my $fh, '>', 'abc' or die "Can't open 'abc': $!"; 
open my $fh2, '>', 'def' or die "Can't open 'def': $!"; 
open my $fh3, '>', 'xyz' or die "Can't open 'xyz': $!"; 

select $fh; 
print "First\n"; 

# Later 
select $fh2; 
print "Second\n"; 

# Later 
select $fh3; 
print "Third\n"; 

# Later 
select STDOUT; 
print "Fourth\n"; 
3

ローカライズST​​DOUT。その後、限られたダイナミックな範囲で別名を付けることができます。そのスコープを離れると、STDOUTは正常に戻ります。

use strict; 
use warnings; 

print_stuff('Normal STDOUT'); 

{ local *STDOUT; 
    open(STDOUT, '>', 'out') 
     or die "Can't redirect STDOUT: $!"; 
    local $| = 1; # Unbuffer handle. 
        # Do this AFTER redirecting STDOUT. 

    print_stuff('Aliased to out'); 

    sleep 10; 
} 


print_stuff('Back to normal STDOUT'); 

sub print_stuff { 
    print join "\n", @_, ''; 
} 
0

ファイルハンドルを短時間しか使用しない場合は、匿名ブロックに入れます。これは、非グローバル変数のスコープを自動的に制限します。追加の利点として

{ 
    open my $fh, '>', 'abc'; 
    print $fh "assorted data"; 
    close $fh; 
} 

変数がスコープの外に出たとき、それは自動的に閉じられますので、あなたも、 「close $fh;」 ラインを持っている必要がありますする必要はありません。

この手法を使用する場合は、コードブロック内で変更されたグローバル変数を常にローカライズする必要があります。

{ 
    local *FH; 
    open FH, '>', 'abc'; 
    print FH "assorted data"; 
    close FH; 
} 
関連する問題