About user Perl
I have a question about the range operator in Perl. The code is here:
#! /usr/bin/perl open FILE, "<test.txt"; while (<FILE>) { print if (1 .. 5); } close FILE; The content in test.txt looks something like this:
1 2 3 4 5 The result of the code is all five lines of the file. It makes no difference when I use print if (1 ... 5) . I think it should print 4 lines.
Is there something that I made a mistake?
Can you help me?
Thanks in advance.
Brs
Ruan
Actually the contents of the file does not matter. However, the line number (of each line being processed) is important, since this is checked against each operand of the .. operator. In fact, it can be written as ...
print if ($. == 1) .. ($. == 5); According to the rules of flip-flopping, print will start when the line number becomes 1, and ends when the line number becomes 5. The only difference between .. and ... in flip-flop is to check both operands on the same expression, which in this case does not matter.
What you might want to use is ...
print if $_ ~~ [1..5]; ... that is, testing the contents of a string in a range. But there is no difference between .. and ... in the context of the list - they both return the same range:
print for (1..5); # 12345 print for (1...5); # 12345 as well And now something ... well, not at all different. ) Consider the following :
while (<DATA>) { print '..', $_ if 1..($. >= 1); print '...', $_ if 1...($. >= 1); } __DATA__ 1 2 3 He is typing ...
..1 ...1 ...2 ... and then nothing, because ...
- Operator
Operator..checks both conditions on the same first line. Checking the first condition ($. == 1) turns it on (and makes the result of the whole expression..equal to1). But guess what? Then it turns off immediately, as$. >= 1$. >= 1also evaluated to1(true). When the trigger is off, all of the following lines should pass the first condition again, and this simply cannot be. )...more relaxed. For the first line, since the first condition is true, the gateway opens, but the second expression is not checked here! It will be checked, however, for the second line, closing the gateway, but2manage to get through. )
In your case, this does not matter, since .. cannot use a trigger for the same line number.
To quote perlop :
In a scalar context, "
.." returns a boolean value. The operator is bistable, like a trigger, and emulates the linear range (comma) of the sed , awk operator and various editors. The operator ".." maintains its own Boolean state, even through a subroutine containing It. This is not true as long as its left operand is false. Once the left operand is true, the range operator remains true until the right operand is true, AFTER which the range operator again becomes false. This does not become false until the next time the range of the operator is evaluated. It can test the right operand and become false on the same evaluation became valid (as in awk ), but it still returns true. If you do not want him to check the operand before the next evaluation, as in sed , just use three dots ("...") instead of two. In all other respects, "..." behaves the same as "..".The correct operand is not evaluated while the operator is in the βfalseβ state, and the left operand is not evaluated when the operator is in the βtrueβ state. Priority is a little lower
||and&&. The return value is either an empty string for false or a sequence number (starting with 1) for true. The reset sequence number for each range detected. The final number sequence in the range has the string "E0" attached to it, which does not affect its numerical value, but gives you something to look for if you want to exclude the endpoint. You can exclude the starting point, expecting the sequence number to be greater than 1.If any operand of the scalar "
.." is a constant expression, this operand is considered true if it is equal (==) to the current input line number ($.).
Thank you for your answers that enlighten me. After reading perldoc and doing some testing, I want to share my understanding here. If something is wrong, pls let me know. :)print if (1 .. 5) is a shortcut for print if ($. == 1 .. $. == 5) .
The initial state of the expression is false after reading the first line of $. == 1 $. == 1 is executed, and the state goes true. Therefore, the first line is printed. Then the second line, the third, fourth. When it comes to the fifth line, the state is still true . This is a condition that decides whether to go to a block. So the fifth line is also printed, then $. == 5 $. == 5 is executed, at this time the next state becomes false, therefore, if there was a line after that, they will not be printed.
There is no difference between .. and ... , because the difference only occurs when the left operand returns true. Let me show this:
Example here: perlop . This example first confuses me, let me show my understanding.
@lines = (" - Foo", "01 - Bar", "1 - Baz", " - Quux"); foreach (@lines) { if (/0/ .. /1/) { print "$_\n"; } } When it comes to "01 - Bar", /0/ is executed, so the state becomes true. And at the same time, /1/ also executed, so the next state suddenly becomes false, here .. differs from ... because ... will not evaluate /1/ , and the next state will still be true. So "1 - Baz" will not be printed. Otherwise, when used ... , this string can be printed.
In Perl, something is false if it returns either undef , an empty string, or a value of 0. Otherwise, true is considered.
Your saying:
print if (1..5); This means that the contents of $_ will be printed if (1..5) returns a true value. So, (1..5) returns an array of five members. This means that if (1..5) always true, and every line in your file will be printed.