1

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

我正在使用语句来解决上述问题..但是使用和语句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在倒数第二个中添加 a when,因为我只希望default在没有执行的when情况下执行我的..

这里的问题是,如果最后一个when条件为 false,它不会进入块,然后它继续执行default即使我的前两条when语句都已满足。

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

所以,在上面的代码中,我已经交换了-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
}

所以,我想问一下,如何处理这些情况..我希望它像given-when添加到 Perl 中的语句一样工作..
它应该检查所有,如果至少执行了一个,则when跳过..defaultwhen

4

3 回答 3

2

由于default不是“其他条件”,但可以看作是when that always match,因此对于您正在尝试做的事情来说,这并不是一个很好的匹配。在您的默认情况下,您对该块中的早期匹配一无所知,并且您不能在不知道以后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" }      
}
于 2012-09-29T11:08:39.740 回答
2

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

stat $file;
if ( -r _ ) { ... }
if ( -w _ ) { ... }
于 2012-09-30T05:29:15.930 回答
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 原则

另一种方法是使用 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 回答