关于Perl范围运营商

rua*_*hao 7 perl

我对Perl中的范围运算符有疑问.代码在这里:

 #! /usr/bin/perl
 open FILE, "<test.txt";
 while (<FILE>) {
     print if (1 .. 5);
 }
 close FILE;
Run Code Online (Sandbox Code Playgroud)

test.txt中的内容类似于:

 1
 2
 3
 4
 5
Run Code Online (Sandbox Code Playgroud)

代码的结果是文件的所有五行.我使用时没有区别print if (1 ... 5).我认为它应该输出四行.我犯了什么错吗?

rai*_*7ow 8

这里的文件内容实际上并不重要.然而,重要的是行号(每个处理行的行号),因为它是针对运算..符的每个操作数进行检查的.它实际上可以写成......

print if ($. == 1) .. ($. == 5);
Run Code Online (Sandbox Code Playgroud)

根据触发规则,print当行号变为等于1时将开始工作,并且当行号变为等于5时结束.触发器之间.....触发器之间的唯一区别是关于在同一表达式上测试两个操作数,在这种情况下不相关.

你可能想要使用的是......

print if $_ ~~ [1..5];
Run Code Online (Sandbox Code Playgroud)

...也就是说,在一个范围内测试该行的内容.但有没有什么区别..,并...在列表环境-它们都返回相同的范围:

print for (1..5); # 12345
print for (1...5); # 12345 as well
Run Code Online (Sandbox Code Playgroud)

现在有些东西......好吧,不是那么完全不同.)考虑以下事项:

while (<DATA>) {
  print '..', $_  if 1..($. >= 1);
  print '...', $_ if 1...($. >= 1);
}
__DATA__
1
2
3
Run Code Online (Sandbox Code Playgroud)

它打印...

..1
...1
...2
Run Code Online (Sandbox Code Playgroud)

......然后什么都没有,因为......

  • ..运营商的检查在相同的条件下-第一-行.检查第一个条件($. == 1)将其打开(并使整个..表达式的结果等于1).但猜猜怎么了?它会立即关闭,$. >= 1同时评估为1(true).当触发器关闭时,所有下一行必须再次通过第一个条件,这是不可能发生的.

  • ...操作更轻松.对于第一行,由于第一个条件是真实的,网关是打开的 - 但是这里没有检查第二个表达式!但是,对于第二行,关闭网关将进行检查 - 但仍2设法通过.


Сух*_*й27 5

在你的情况下,由于无法..对同一行号进行触发,因此无关紧要.

引用perlop:

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

当操作符处于"false"状态时,不评估右操作数,并且当操作符处于"true"状态时,不评估左操作数.优先级略低于||&&.返回的值是false的空字符串,或者是true的序列号(以1开头).为遇到的每个范围重置序列号.范围中的最终序列号附加了字符串"E0",它不会影响其数值,但如果要排除端点,则可以搜索一些内容.您可以通过等待序列号大于1来排除起点.

如果标量" .."的任一操作数是常量表达式,则如果该操作数==与当前输入行号($.变量)相等() ,则该操作数被视为true .