Book Home Programming PerlSearch this book

3.15. Range Operator

The .. range operator is really two different operators depending on the context.

In scalar context, .. returns a Boolean value. The operator is bi-stable, like an electronic flip-flop, and emulates the line-range (comma) operator of sed, awk, and various editors. Each scalar .. operator maintains its own Boolean state. 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. The operator doesn't become false until the next time it is evaluated. It can test the right operand and become false on the same evaluation as the one where it became true (the way awk's range operator behaves), but it still returns true once. If you don't want it to test the right operand until the next evaluation (which is how sed's range operator works), just use three dots (...) instead of two. With both .. and ..., the right operand is not evaluated while the operator is in the false state, and the left operand is not evaluated while the operator is in the true state.

The value returned is either the null string for false or a sequence number (beginning with 1) for true. The sequence number is reset for each range encountered. The final sequence number in a range has the string "E0" appended to it, which doesn't affect its numeric value, but gives you something to search for if you want to exclude the endpoint. You can exclude the beginning point by waiting for the sequence number to be greater than 1. If either operand of scalar .. is a numeric literal, that operand implicitly compared to the $. variable, which contains the current line number for your input file. Examples:

if (101 .. 200) { print; }  # print 2nd hundred lines
next line if (1 .. /^$/);   # skip header lines
s/^/> / if (/^$/ .. eof()); # quote body
In list context, .. returns a list of values counting (by ones) from the left value to the right value. This is useful for writing for (1..10) loops and for doing slice operations on arrays:
for (101 .. 200) { print; }            # prints 101102...199200
@foo = @foo[0 .. $#foo];               # an expensive no-op
@foo = @foo[ -5 .. -1];                # slice last 5 items
If the left value is greater than the right value, a null list is returned. (To produce a list in reverse order, see the reverse operator.)

If its operands are strings, the range operator makes use of the magical autoincrement algorithm discussed earlier.[4] So you can say:

@alphabet = ('A' .. 'Z');
to get all the letters of the (English) alphabet, or:
$hexdigit = (0 .. 9, 'a' .. 'f')[$num & 15];
to get a hexadecimal digit, or:
@z2 = ('01' .. '31');  print $z2[$mday];
to get dates with leading zeros. You can also say:
@combos = ('aa' .. 'zz');
to get all combinations of two lowercase letters. However, be careful of something like:
@bigcombos = ('aaaaaa' .. 'zzzzzz');
since that will require lots of memory. More precisely, it'll need space to store 308,915,776 scalars. Let's hope you allocated a very large swap partition. Perhaps you should consider an iterative approach instead.

[4] If the final value specified is not in the sequence that the magical increment would produce, the sequence continues until the next value is longer than the final value specified.



Library Navigation Links

Copyright © 2002 O'Reilly & Associates. All rights reserved.