4

私のコードは " " の直前の最後の行を実行しませんexit;。その理由がわかりません。printf $fhの前に追加の行を追加しようとしましたexitが、それも機能しませんでした。どちらの行も印刷されません。終了前の最後の印刷ステートメントを除いて、他のすべては正常に印刷されます。

なぜこれが起こるのか手がかりはありますか?または、さらに良いことに、それを修正または回避する方法は?

    if($i>0 && $i<3)
    {
        printf $fh "Partial match found.\n";
        if($matched_uid){printf $fh "UID #: ".$arguid." exists.\n";}
        if($matched_id){printf $fh "ID #: ".$argid." exists.\n";}
        if($matched_uname){printf $fh "Username: ".$arguname." exists.\n";}
        printf $fh "Aborting."; 
        exit;
    }

編集:
私がコピーしたコードの一部にはこれが含まれていました

select $fh; $| = 1; #set auto flush

たぶんこれが私の結果を複製できなかった理由です....

4

6 に答える 6

10

私はR. Bemroseに投票しましたが、$fh がFILE HANDLEcloseである場合は、終了する前にそれを使用することもできます。

また、printf間違った使い方をしています。printf は「印刷ファイル」ではありません。その「印刷形式」。

その最後の例では

  print $fh 'Message' ;  

は、あなたが必要とすることすべてです。

printf次のように使用することを意図しています。

printf $fh 'some format %s  and more %s ' ,  $var , $var ; 

また

   printf 'some format %s  and more %s ' ,  $var , $var ; 

そしてそれはすることと同等です

   print $fh sprintf 'format %s more %s' , $var , $var ; 

このため、連結された変数のいずれかが展開されて「%」が含まれる場合に、不要なコード リスクが発生します。この罠に陥る例については、Q:308417: Perl スクリプトがファイルから文字を削除するのはなぜですか?を参照してください。

perldoc -f print

ファイルハンドルリストを出力
リストを印刷
print 文字列または文字列のリストを出力します。

perldoc -f printf

printf ファイルハンドル形式、リスト
printf フォーマット、リスト
      「$\」を除いて、「print FILEHANDLE sprintf(FORMAT, LIST)」と同等
      (出力レコード区切り) は追加されません

さらなる調査

「バッファリング」状態が発生しないため、問題をさらに調査しました。フラッシュするかどうかに関係なく、すべてのファイルが適切にフラッシュされます。(Perl 5.10)。

私が試しているコードスニペットは次のとおりです。

#!/usr/bin/perl 

use strict;
use warnings;


open my $fh , '>' , '/tmp/oo.txt'; 

my $exit_at = int(rand( 200_000 ));
print "$exit_at\n";
sleep 2;
for ( 0 .. ( $exit_at * 2 ) ){ 
    print $fh $_;
    if ( $_ == $exit_at ){
        printf $fh '%n' ; # Bad Code Causes Early Death. 
        printf $fh 'last line';
        exit; 
    }
    if ( $_ % 1000  ){
        print $fh "\n";
    }
}

私はprintfの誤用を使用しています。コメントされた行は、「n」パラメーターを提供していないために有効ではないため、エラーメッセージを排出し、次のように終了します。

Modification of a read-only value attempted at iotest.pl line 15.

「最後の行」の印刷を実行する前に(これも悪いですが、%記号がないので問題ありません)、出力ファイルに「最後の行」がありません。

printf を修正し、代わりに plain-old-print を使用して、問題が解決するかどうかを確認してください。

于 2009-03-11T20:02:37.963 に答える
9

Perl はその出力をバッファリングします。で自動バッファリングをオフにすることができます

local $| = 1;

編集:何とかヒット!|の代わりに 初めて...修正されました。それがどのように起こったのかわかりません。それらはキーボードの反対側にあります。

于 2009-03-11T19:58:32.403 に答える
8

「中止します。\n」を試してください。

これはバッファリングの問題のようです。

于 2009-03-11T19:57:26.680 に答える
3

の適切な使用に関してprint、あなたは物事を自分自身に少し難しくしています。

文字列を連結する代わりに、変数を補間します。複数の文字列ではなく、印刷する文字列のリストを含む 1 つの print ステートメントを使用します。

1 つの方法を次に示します。

if( $i>0 && $i<3 )
{
    print $fh join "\n", 
        "Partial match found.",
        $matched_uid   ? "UID #: $arguid exists."      : (),
        $matched_id    ? "ID #: $argid exists."        : (),
        $matched_uname ? "Username: $arguname exists." : (),
        "Aborting.",
        ;

    exit;
}

三項演算子の()false 側は空のリストであり、結合する引数が平坦化されると消えます。空の文字列 ( '') を使用した場合、一致しない基準ごとに、結果に余分な空白行が生成されます。

各項目に独自の改行を追加して、結合をスキップすることもできます。これが読みやすいと思われる場合:

    print $fh  
        "Partial match found.\n",
        $matched_uid   ? "UID #: $arguid exists.\n" : '',
        ...
于 2009-03-12T05:09:23.860 に答える
2

最後の printf の末尾に \n を追加する必要があります。そうしないと、出力がコンソールにフラッシュされません。

于 2009-03-11T19:58:07.473 に答える
0

デビッド・ノーマンが正しいか、問題は別の場所にあります。if ブロック内のコードを perl インタープリターに入力したところ、「中止中」と出力されました。予想通り。(改行文字がなくてもうまくいきました。)

于 2009-03-11T20:01:31.787 に答える