Оператор диапазона «..» в Perl
Освежая свои знания по Perl, я наткнулся на место, которое оказалось недостаточно документировано. Вернее, в английском оригинале есть нетривиальное описание, которое в русском переводе документации вообще пропущено. Речь идет о поведении оператора диапазона «..» в скалярном контексте, которое мне вроде удалось-таки расшифровать.

Каждый оператор диапазона «A..B» в тексте программы в скалярном контексте имеет два логических состояния - истина и ложь, в которых его значение вычисляется по-разному.
Этот оператор обычно используется при поиске каких-либо диапазонов во входящих последовательностях строк.
Вычисляется значение этого оператора таким образом:
| Состояние | Значение | Условие смены состояния | Примечание |
| Ложь | Пустая строка (ложь). | Истинное значение операнда A меняет состояние оператора на «истина». | Начальное состояние оператора B не вычисляется. |
| Истина | Последовательное число (начиная с 1), равное тому, сколько раз подряд оператору удалось оставаться в состоянии «истина». | Истинное значение операнда Вменяет состояние оператора на «ложь» | A не вычисляется. |
ПРИМЕР 1
@lines = ( " - Foo",
"0 - Bar",
" - Faa",
"1 - Baz",
" - Quux");
foreach(@lines)
{
if (/0/ .. /1/)
{
print "$_n";
}
выдаст диапазон из трех строк (начиная с содержащей символ “0″, и заканчивая содержащей “1″)
0 - Bar
- Faa
1 - Baz
Переход истина->ложь:
В момент перехода в состояние «ложь» оператор возвращает последнюю истину - число с приклееными символами “E0″ (это не влияет на числовое значение результата, но позволяет выполнить строковую проверку на E0, если нужно исключить последний элемент).
ПРИМЕР 2
@lines = ( " - Foo",
"0 - Bar",
" - Faa",
"1 - Baz",
" - Quux");
foreach(@lines) {
my $s= /0/ .. /1/;
if ($s){ print "$st(".int($s)."):t$_n";}
}
Напечатает:
1 (1): 0 - Bar
2 (2): - Faa
3E0 (3): 1 - Baz
Переход ложь->истина:
Если операнд A принял значение истина, то оператор переключается в состояние «истина» и на этой же итерации вычисляет операнд B, и если B окажется истиным, то оператор вернет последнюю истину и опять переключиться в состояние «ложь».
Чтобы избежать проверки на этом переходе правого операнда, используется оператор «…» (который в остальном эквивалентен «..»).
ПРИМЕР 3
@lines = ( " - Foo",
"01 - Bar",
" - Faa",
"1 - Baz",
" - Quux");
foreach(@lines) {
my $s= /0/ .. /1/;
if ($s) { print "$s: $_n";}
}
Выдаст:
1E0: 01 - Bar
Но в случае
my $s= /0/.../1/;
выдаст:
1: 01 - Bar
2: - Faa
3E0: 1 - Baz
Умолчания:
Если какой-то из двух операндов A или B является константой, то этот операнд будет вычисляется как истина, если он равен (как целое число) номеру текущей строки ввода ($.)
ПРИМЕР 4.
if (101 .. 200) { print; }
печатает 2-ю сотню строк, то же что
if($. == 101 .. $. == 200) { print; }
а код
next line if (1 .. /^$/);
пропустит заголовок почтового сообщения (пустая строка /^$/ значит конец заголовка) - то же, что
next line if ($. == 1 .. /^$/);
