Question: Let's say I have a file called text.txt that has this

```
one
two
three
four
five

```

If I have this in a perl script

```
open($fh, '<', text.txt) or die "blah blah";
while(<$fh>){
   print if 2..4;
}

```

it will print two, three and four. How is that if statement comparing $\_ with the range 2..4 in the background? In other words, If I use a different variable like $line instead of $\_, what would I have to write that if comparison? 

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

```

Thank you. I love Perl, but there are a few things that I can't understand how it does them in the background.

Answer: 
There is certain amount of magic between range operator and `$.` built-in variable, which is described in following sentence from [perlop](http://perldoc.perl.org/perlop.html#Range-Operators) (emphasis mine):

> 
> If **either** operand of scalar `".."` is a **constant expression**, that
>  operand is considered true if it is equal (`==` ) to the current input
>  line number (the `$.` variable).
> 
> 
> 

Essentially, the `$.` is a number of processed line (starting by one), which is compared with range. You may obtain the same result using named variable simply as:

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

```

or if your prefer to write full-fledged if statement, there is an equaivalent form:

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

```

The complete, self-contained solution may be written as:

```
#!/usr/bin/env perl

use strict;
use warnings;

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

__DATA__
one
two
three
four
five

```

yielding output as:

```
two
three
four

```
From [Range operators](http://perldoc.perl.org/perlop.html#Range-Operators),

> 
> In scalar context, `".."` returns a boolean value. The operator is bistable, like a flip-flop, and emulates the line-range (comma) operator of **sed**, **awk**, and various editors. Each `".."` operator maintains its own boolean state, even across calls to a subroutine that contains it. It is false as long as its left operand is false. Once the left operand is true, the range operator stays true until the right operand is true, *AFTER* which the range operator becomes false again. It doesn't become false till the next time the range operator is evaluated. It can test the right operand and become false on the same evaluation it became true (as in **awk**), but it still returns true once. If you don't want it to test the right operand until the next evaluation, as in **sed**, just use three dots (`"..."`) instead of two. In all other regards, `"..."` behaves just like `".."` does.
> 
> 
> 

---

For example,

```
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',
   );
}

```

Output:

```
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)` is when the operator starts returning true.
* `($i == 6 || $i == 2)` is when the operator stops returning true.

---

```
if 2..4

```

is short for 

```
if ($. == 2) .. ($. == 4)

```

which is short for

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

```

And since `$.` usually increases monotonously, it's equivalent to

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

```