Опубликован: 18.06.2007 | Доступ: свободный | Студентов: 1354 / 35 | Оценка: 4.14 / 3.29 | Длительность: 12:44:00
ISBN: 978-5-94774-604-4
Лекция 4:

Операторы m// и s///

< Лекция 3 || Лекция 4: 1234 || Лекция 5 >

4.2. Алгоритм работы операторов m// и s///

В языке Perl есть такое понятие - контекст выражения. Операторы могут возвращать значение, которое зависит от того, чему оно присваивается. Если оно присваивается скалярной переменной, то возвращаемое значение может быть одно, а если присвоение происходит массиву, то возвращаться может уже список значений. Таким является оператор m//. Например, если мы используем его в условии условного оператора:

if (m/…/) { … }

то это скалярный контекст, т.к. в условии ожидается одно значение, которое трактуется как истина или ложь. А если написать

my @m=m/…/;

то это списковый контекст, в котором оператор m// возвратит список значений. Оператор print является списковым, т.к. он ожидает список в качестве своего аргумента, поэтому, если написать

print m/…/;

то это также будет использование оператора поиска в списковом контексте.

4.2.1. Оператор m// в режиме однократного поиска и в скалярном контексте

В режиме однократного поиска (т.е. без модификатора g ) и в скалярном контексте оператор m// возвращает логическое значение: целое число 1, если поиск оказался успешным, или пустую строку в случае неудачи. Если в шаблоне имелись захватывающие скобки, то при успешном поиске создаются нумерованные переменные $1, $2, …, которые содержат соответствующие фрагменты захваченного текста. Если поиск оказался неудачным, то эти переменные хранят последнее состояние от предыдущего оператора поиска или замены.

После успешного поиска также можно использовать специальные переменые:

  • $& - копия текста, совпавшего со всем регулярным выражением. Если вы заключите все регулярное выражение в круглые скобки: m/(…)/, то в случае успеха в переменной $1 получите то же самое значение.
  • $` - копия текста, предшествующего началу совпадения (т.е. текст, который был слева от совпадения).
  • $' - копия текста, следующего после совпадения (т.е. расположенного справа от совпавшего текста). После успешного совпадения текст "$`$&$'" представляет из себя копию исходного текста. Есть малозначительное исключение: если оператор m// был успешно применен к неопределенной переменной, то эти специальные переменные будут иметь пустые значения.
  • $+ - копия переменной $1 или $2… с максимальным номером, которой было присвоено значение. Если в регулярном выражении нет сохраняющих скобок или они не задействованы в совпадении, то эта переменная получает неопределенное значение.
  • $^N - копия переменной $1 или $2…, которая соответствует последней только что закрытой паре скобок на момент использования этой переменной. Если в регулярном выражении нет сохраняющих скобок или они не задействованы в совпадении, то эта переменная получает неопределенное значение.
  • @ - массив начальных смещений в целевом тексте. $-[0] хранит смещение начала совпадения от начала текста для всего регулярного выражения. $-[1] хранит смещение начала совпадения от начала текста для фрагмента текста, захваченного в переменную $1, $-[2] - для переменной $2 и т.д.
  • @+ - аналогичный массив конечных смещений в целевом тексте. Т.е. смещений символов, следующих за конечными символами совпадения во всем тексте, в переменной $1, $2 и т.д. Имеет место соотношение substr($text,$-[0],$+[0]-$-[0]) эквивалентно $&, substr($text,$-[1],$+[1]-$-[1]) эквивалентно $1 и т.д.

Теперь буду давать пояснения к этому списку. Во-первых, имейте в виду, что переменная $0, похожая на нумерованную, не имеет отношения к регулярным выражениям, а хранит имя сценария Perl, запущенного на выполнение.

Начинающие часто путают специальные переменные $+ и $^N, между которыми имеется тонкое различие. Сначала рассмотрим пример использования переменной $+. Пусть в регулярном выражении мы имеем альтернативную конструкцию, альтернативы которой заключены в захватывающие скобки:

$text =~ /(…)|(…)|(…)/;

Мы знаем, что совпадение может быть не более чем с одной альтернативой, и хотим получить фрагмент текста, совпавшего с какой-либо альтернативой. Не будь переменной $+, нам пришлось бы перебирать переменные $1, $2,… и определять, какая из них имеет определенное значение.

Для понимания отличия переменной $+ от $^N рассмотрим такой пример:

print "\$+=$+, \$^N=$^N" if "abc" =~ /(a(bc))/;

На печати окажется строка

$+=bc, $^N=abc

Различие происходит от того, что скобки могут быть вложенными. Нумерованная переменная с наибольшим номером здесь $2, а последними закрываются скобки у переменной $1.

Использовать значения переменных $+ и $^N можно также в коде Perl внутри регулярного выражения. Эти переменные корректируются после того, как закроется очередная захватывающая скобка. Например:

print "\$+=$+, \$^N=$^N"
 if "abcd" =~ /(a(bc)(d)(?{ print "\$+=$+, \$^N=$^N\n" }))/;

Здесь выводятся значения переменных $+ и $^N после третьей скобки внутри регулярного выражения, а также после того, как оператор поиска отработал. В итоге получается результат:

$+=d, $^N=d
$+=d, $^N=abcd

$+ в обоих случаях относится к нумерованной переменной с максимальным номером - $3, а переменная $^N внутри регулярного выражения копирует переменную $3, а вне регулярного выражения является копией переменной $1.

< Лекция 3 || Лекция 4: 1234 || Лекция 5 >
Константин Бражников
Константин Бражников
Россия
Mike .
Mike .
Россия