如果`foreach-when`语句中的最后一个`when`语句为false,则始终执行default语句

时间:2012-09-29 10:45:43

标签: perl

在我的程序中,我将file names的命令行列表传递给我的程序,并检查每个文件是否为executablereadablewritable

我正在使用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
}

我添加了一个continue,只对前两个when进行了perl检查所有条件,无论文件名是什么..

另外,我没有在后一个continue添加when,因为如果default都没有执行,我只希望执行when ..

问题在于,如果最后when条件为假,则不会进入该区块,然后继续执行default 即使我的前两个when语句也已满足。

我通过更改when的顺序检查了此问题的原因,并看到如果只执行了最后一次when,则会看到没有continue,因此它不会执行default语句..

所以,在上面的代码中,我交换了-x-r ..我的文件是可读的,所以在这种情况下最后when将被执行..然后我的{ {1}}语句未执行..

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,如果执行了至少一个when,请跳过default

3 个答案:

答案 0 :(得分:2)

由于default不是“其他条件”,但是当它总是与匹配时可以被视为,因此它与您尝试执行的操作不太匹配。在您的默认情况下,您不知道该块中早期匹配的任何内容,并且您不能在不知道以后when是否匹配的情况下先断开局部化器,因此您必须“破解它” “使用一个布尔表示早期匹配的一个,或者只是将它交换为处理”遗留“条件的时间;

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" }      
}

答案 1 :(得分:2)

请注意,perl不会按文件名缓存stat结果,因此您将一遍又一遍地说明同一文件。它确实提供了上次发布的统计信息的“_”缓存,因此您可以:

stat $file;
if ( -r _ ) { ... }
if ( -w _ ) { ... }

答案 2 :(得分:1)

switch语句最适用于“其中一个匹配”。在多个案例可能匹配的情况下使用它会导致必须滥用逻辑结构才能使其工作。必须使用漏洞,并使您的案例依赖于订单,这是一个危险信号。

更好的选择可能是创建一系列匹配。

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";
    }
}

构建数组具有更灵活的良好副作用。您可以打印一行或几行。它还避免了在最后再次重复所有标志,这违反了DRY Principle

另一种方法是使用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并且很容易被遗忘,而对于数组,数据和标志是相同的。