如何从给定/何时构造的内部开始跳转到下一次迭代?

时间:2014-04-16 08:39:02

标签: perl while-loop switch-statement

#!/usr/bin/perl

use feature "switch";
use strict;
use warnings;

while (<DATA>) {
  given ($_) {
    when ("abc" or "def") {
      # ...
      next;
    }
    when (/\w{3}/) {
      print $_;
      next;  
    }

}

__DATA__
abc
def
ghi
lmn
opq
rst
uvz

我有这个输出:

abc
def
ghi
lmn
opq
rst
uvz

但我想要这个:

ghi
lmn
opq
rst
uvz

我不知道自己错过了什么,请帮忙。

2 个答案:

答案 0 :(得分:1)

首先,请勿使用given / when。它构建的smartmatch功能是失败的,应该避免。写这个的正确方法是:

use strict;
use warnings;
use feature 'say';

while (<DATA>) {
    chomp;
    next if $_ eq 'abc' or $_ eq 'def';
    say $_;
}

但回到given / when。由于某种原因,when ("abc" or "def")条件被解析为when ("abc")(通过在perl -MO=Deparse下运行脚本来验证这一点)。如果要对一组值进行智能匹配,请使用数组:when (["abc", "def"])

该条件仍然不匹配,因为$_是一个带尾随换行符的字符串。您需要先chomp

当然,next块内的when完全没必要。与C&#39 {s} switch / case不同,没有隐含的漏洞。要显式继续匹配,可以使用continue命令。所以你的代码可以重写为:

while (<DATA>) {
  chomp;
  given ($_) {
    when (["abc", "def"]) {
       # do nothing
    }
    when (/\w{3}/) {
      print "$_\n";
    }
  }
}

但是我们假设它已经写好了

while (<DATA>) {
  chomp;
  given ($_) {
    when (["abc", "def"]) {
       # do nothing
    }
    when (/\w{3}/) {
      print $_;
    }
  }
  print "\n";
}

所以我们必须跳过print "\n"。在这种情况下,我们可以使用循环标签:

LINE:
while (<DATA>) {
  chomp;
  given ($_) {
    when (["abc", "def"]) {
       next LINE;
    }
    when (/\w{3}/) {
      print $_;
    }
  }
  print "\n";
}

任何循环控制命令,如nextredolastcontinue都可以使用标签来引用某些外循环。

答案 1 :(得分:1)

不幸的是,given/when有点麻烦并且标记为实验性的。围绕它存在一些争议。您可以找到有关the experimental details here的更多信息。

在您的上下文中,您可以使用break打破封闭的给定块

#!/usr/bin/perl
use strict;
use warnings;
use feature "switch";

while (<DATA>) {
    given ($_) {
        break when (["abc\n","def\n"]);
        when(/\w{3}/) {
            print $_;
            break;
        }
    }
};

__DATA__
abc
def
ghi
lmn
opq
rst
uvz