user3616128
user3616128

Reputation: 377

Usage of Range operator in perl

I have the following code especially the condition in the if block and how the id is being fetched, to read the below text in the file and display the ids as mentioned below:

Using a Range operator ..:

use strict;
use warnings;
use autodie;

#open my $fh, '<', 'sha.log';
my $fh = \*DATA;

my @work_items;

while (<$fh>) {
    if ( my $range = /Work items:/ ... !/^\s*\(\d+\) (\d+)/ ) {
        push @work_items, $1 if $range > 1 && $range !~ /E/;
    }
}

print "@work_items\n";

Text in the file

__DATA__
Change sets:
  (0345) ---$User1 "test12"
    Component: (0465) "textfiles1"
    Modified: 14-Sep-2014 02:17 PM
    Changes:
      ---c- (0574) /<unresolved>/sha.txt
    Work items:
      (0466) 90516 "test defect
      (0467) 90517 "test defect
Change sets:
  (0345) ---$User1 "test12"
    Component: (0465) "textfiles1"
    Modified: 14-Sep-2014 02:17 PM
    Changes:
      ---c- (0574) /<unresolved>/sha.txt
    Work items:
      (0468) 90518 "test defect

Outputs:

90516 90517 90518

Question: Range operator is used with two dots why it is being used with 3 dots here??

Upvotes: 2

Views: 194

Answers (2)

ikegami
ikegami

Reputation: 385764

First, its not really the range operator; it's known as the flip-flop operator when used in scalar context. And like all symbolic operators, it's documented in perlop.

... is almost the same thing as ... When ... is used instead of .., the end condition isn't tested on the same pass as the start condition.

$ perl -E'for(qw( a b a c a d a )) { say if $_ eq "a" .. $_ eq "a"; }'
a     # Start and stop at the first 'a'
a     # Start and stop at the second 'a'
a     # Start and stop at the third 'a'
a     # Start and stop at the fourth 'a'

$ perl -E'for(qw( a b a c a d a )) { say if $_ eq "a" ... $_ eq "a"; }'
a     # Start at the first 'a'
b
a     # Stop at the second 'a'
a     # Start at the third 'a'
d
a     # Stop at the fourth 'a'

Upvotes: 2

ruakh
ruakh

Reputation: 183301

Per http://perldoc.perl.org/perlop.html#Range-Operators:

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.

So, this:

/Work items:/ ... !/^\s*\(\d+\) (\d+)/

means "from a line that matches /Work items:/ until the next subsequent line that doesn't match /^\s*\(\d+\) (\d+)/", whereas this:

/Work items:/ .. !/^\s*\(\d+\) (\d+)/

would mean "from a line that matches /Work items:/ until the line that doesn't match /^\s*\(\d+\) (\d+)/" (even if it's the same one).

Upvotes: 0

Related Questions