1

私のプログラムではfile names、コマンドラインからプログラムにリストを渡し、各ファイルが- executablereadableおよび.であるかどうかを確認していますwritable

上記の問題に対してステートメントを使用しています。しかし、ステートメントforeach-whenの使用に問題があるようです。正しく使用していない可能性がありますが、予期しない結果が発生します。whendefault

これが私のコードです:-

#!/perl/bin
use v5.14;
use warnings;

foreach (@ARGV) {
    say "*************Checking file $_ *******************";
    when (-r $_) { say "File is Readable"; continue; }
    when (-w $_) { say "File is Writable"; continue; }   # This condition is true
    when (-x $_) { say "File is Executable" }   # This condition is false
    default      { say "None of them" }      # Executed
}

ファイルの名前に関係なく、すべての条件をperlでチェックするためcontinueに、最初の2つにのみを追加しました。when

continueまた、最後から2番目にを追加していません。これは、が実行されていない場合whenにのみ実行されるようにするためです。defaultwhen

ここでの問題は、最後のwhen条件がfalseの場合、ブロックに入らず、最初の2つのステートメントが満たされていても実行を続けることです。defaultwhen

の順序を変えてこの問題の原因を確認したwhenところ、最後だけwhenを実行すると、がないことがわかりcontinuedefaultステートメントが実行されないことがわかりました。

したがって、上記のコードでは、スワップ-xして-r..ファイルが読み取り可能であるためwhen、この場合は最後に実行されます..その後、defaultステートメントは実行されません。

#!/perl/bin
use v5.14;
use warnings;

foreach (@ARGV) {
    say "*************Checking file $_ *******************";
    when (-x $_) { say "File is Executable"; continue; }
    when (-w $_) { say "File is Writable"; continue; }
    when (-r $_) { say "File is Readable" }   # This condition is true
    default      { say "None of them" }   # Not executed
}

ですから、このような状況にどう対処するかをお聞きしたいと思います。Perlにgiven-whenステートメントが追加されたのと同じように機能させたいのです。
すべてをチェックし、少なくとも1つが実行されwhenた場合はスキップする必要があります。defaultwhen

4

3 に答える 3

2

これdefaultは「他の条件」ではありませんが、常に一致する場合と見なすことができるため、実行しようとしていることと実際にはよく一致しません。デフォルトの状態では、そのブロック内の以前の一致について何も知らず、後で一致するかどうかを知らずに以前にトピックライザーから抜け出すことはできないためwhen、ブール値で「ハック」する必要があります。以前に一致したものの1つを言うか、「残り」の状態を処理するときにそれを交換します。

foreach (@ARGV) {
    say "*************Checking file $_ *******************";
    when (-r $_)             { say "File is Readable";   continue; }
    when (-w $_)             { say "File is Writable";   continue; }
    when (-x $_)             { say "File is Executable"; continue; }
    when (!-r && !-w && !-x) { say "None of them" }      
}
于 2012-09-29T11:08:39.740 に答える
2

perlはファイル名ごとに統計結果をキャッシュしないため、同じファイルを何度も記述していることに注意してください。最後に発行された統計の「_」キャッシュを提供するため、次のことができます。

stat $file;
if ( -r _ ) { ... }
if ( -w _ ) { ... }
于 2012-09-30T05:29:15.930 に答える
1

switchステートメントは、「これらの1つが一致する」場合に最適です。複数のケースが一致する可能性がある状況でこれを使用すると、論理構造を悪用して機能させる必要があります。フォールスルーを使用する必要があり、ケースを順序に依存させることは、危険信号です。

より良い選択は、一致の配列を作成することかもしれません。

for my $file (@files) {
    my @flags;
    push @flags, "readable"   if -r $file;
    push @flags, "writable"   if -w $file;
    push @flags, "executable" if -x $file;

    if( @flags ) {
        printf "%s is %s\n", $file, join(", ", @flags);
    }
    else {
        say "$file has no flags set";
    }
}

アレイを構築すると、柔軟性が向上するという優れた副作用があります。1行または複数行を印刷できます。また、DRY原則に違反する、最後にすべてのフラグを再度繰り返す必要がなくなります。

別の方法は、doブロックを使用してフラグを設定することです。

for my $file (@files) {
    my $has_flags;
    do { say "$file is readable";   $has_flags = 1; } if -r $file;
    do { say "$file is writable";   $has_flags = 1; } if -w $file;
    do { say "$file is executable"; $has_flags = 1; } if -x $file;

    if( !$has_flags ) {
        say "$file has no flags set";
    }
}

私は主に、マッチの配列を構築することの優位性を強調するためにこれに言及します。フラグを使用すると、各条件が即座にアクションを実行する必要があり、柔軟性が低下するという欠点があります。DRYに違反し、忘れがちなフラグを繰り返し設定する必要がありますが、配列ではデータとフラグは同じものです。

于 2012-09-30T01:02:13.607 に答える