范围运算符如何使用常量,例如`print if 2..4`?

时间:2016-08-09 20:51:44

标签: perl

我们说我有一个名为text.txt的文件,其中包含此

one
two
three
four
five

如果我在perl脚本中有这个

open($fh, '<', text.txt) or die "blah blah";
while(<$fh>){
   print if 2..4;
}
它将打印两个,三个和四个。那个if语句如何在背景中将$ _与范围2..4进行比较?换句话说,如果我使用一个不同的变量,比如$ line而不是$ _,如果进行比较,我还需要写什么?

while(my $line = <$fh>){
   print if........... 2..4   ?????????
}

谢谢。我喜欢Perl,但有一些事情我无法理解它是如何在后台完成的。

2 个答案:

答案 0 :(得分:4)

范围运算符和$.内置变量之间存在一定的魔力,后面的句子来自perlop(强调我的):

  

如果标量".."操作数是常量表达式,那么   如果操作数与当前输入相等(==),则认为该操作数为真   行号($.变量)。

基本上,$.是一系列处理过的行(从1开始),与范围进行比较。您可以使用命名变量获得相同的结果,简单如下:

while (my $line = <$fh>) {
   print $line if 2..4;
}

或者如果您更喜欢撰写完整的if语句,则有一种等价形式:

while (my $line = <$fh>) {
    if (2..4) {
        print $line;
    }
}

完整的,独立的解决方案可以写成:

#!/usr/bin/env perl

use strict;
use warnings;

while (my $line = <DATA>) {
    print $line if 2..4;
}

__DATA__
one
two
three
four
five

产生输出:

two
three
four

答案 1 :(得分:3)

来自Range operators

  

在标量上下文中,".."返回一个布尔值。运算符是双稳态的,如触发器,并模拟 sed awk 和各种编辑器的行范围(逗号)运算符。每个".."运算符都维护自己的布尔状态,甚至在调用包含它的子例程时也是如此。只要其左操作数为假,它就是假的。一旦左操作数为真,范围运算符将保持为真,直到右操作数为真, AFTER ,范围运算符再次变为假。在下一次评估范围运算符之前,它不会变为假。它可以测试正确的操作数,并在相同的评估中变为假(如 awk ),但它仍然返回true一次。如果您不希望它在下一次评估之前测试正确的操作数,就像在 sed 中一样,只需使用三个点("...")而不是两个点。在所有其他方面,"..."的行为与".."的行为相同。

例如,

for my $i (1,2,3,4,5,6,7,8,7,6,5,4,3,2,1) {
   printf("%d: %s\n",
      $i,
      ($i == 4) .. ($i == 6 || $i == 2) ? 'true' : 'false',
   );
}

输出:

1: false
2: false
3: false
4: true
5: true
6: true
7: false
8: false
7: false
6: false
5: false
4: true
3: true
2: true
1: false
  • ($i == 4)是操作员开始返回true的时候。
  • ($i == 6 || $i == 2)是操作员停止返回true的时候。
if 2..4

的缩写
if ($. == 2) .. ($. == 4)

的缩写
if !$in
   ? do { $in = 1 if ($. == 2); $in }
   : do { $in = 0 if ($. == 4); 1   }

由于$.通常会单调增加,因此它等同于

if $. >= 2 && $. <= 4