Алгоритм работы операторов m// и s///
В языке Perl есть такое понятие — контекст выражения. Операторы могут возвращать значение, которое зависит от того, чему оно присваивается. Если оно присвавается скалярной переменной, то возвращаемое значение может быть одно, а если присвоение происходит массиву, то возвращаться может уже список значений. Таким является оператор т//. Например, если мы используем его в условии условного оператора
if (in/.../) { ... }
то это скалярный контекст, т.к. в условии ожидается одно значение, которое трактуется как истина или ложь. А если написать ту @т=т/.../;
то это списковый контекст, в котором оператор /«//возвратит список значений. Оператор print является списковым, т.к. он ожидает список в качестве своего аргумента, поэтому, если написать
print ш/.../;
то это также будет использование оператора поиска в списковом контексте.
Оператор m// в режиме однократного поиска и в скалярном контексте
В режиме однократного поиска (т.е. без модификатора g) и в скалярном контексте оператор /«// возвращает логическое значение: целое число 7, если поиск оказался успешным, или пустую строку' в случае неудачи. Если в шаблоне имелись захватывающие скобки, то при успешном поиске создаются нумерованные переменные 57, $2, .... которые содержат соответствующие фрагменты захваченного текста. Если поиск оказался неудачным, то эти переменные хранят последнее состояние от предыдущего оператора поиска или замены.
После успешного поиска также можно использовать специальные переменные:
• S& — копия текста, совпавшего со всем регулярным выражением. Если вы заключите все регулярное выражение в круглые скобки:
то в случае успеха в переменной $1 получите то же самое значение.
- • S' — копия текста, предшествующего началу совпадения (т.е. текст, который был слева от совпадения).
- • S’ — копия текста, следующего после совпадения (т.е. расположенного справа от совпавшего текста). После успешного совпадения текст «$ S&S’» представляет из себя копию исходного текста. Есть малозначительное исключение: если оператор т// был успешно применен к неопределенной переменной, то эти специаіьньїе переменные будут иметь пустые значения.
- • S+ — копия переменной 57 или $2... с максимальным номером, которой было присвоено значение. Если в регулярном выражении нет сохраняющих скобок или они не задействованы в совпадении, то эта переменная получает неопределенное значение.
- • S^N — копия переменной $1 или $2..., которая соответствует последней только что закрытой паре скобок на момент использования этой переменной. Если в регулярном выражении нет сохраняющих скобок или они не задействованы в совпадении, то эта переменная получает неопределенное значение.
- • @--массив начальных смещений в целевом тексте. $-[0] хранит
смещение начала совпадения от начала текста для всего регулярного выражения. $-[// хранит смещение начала совпадения от начала текста для фрагмента текста, захваченного в переменную $1, $-[2] — для переменной $2 и т. д.
• @+ — аналогичный массив конечных смещений в целевом тексте. Те. смещений символов, следующих за конечными символами совпадения во всем тексте, в переменной $1, $2 и т.д. Имеет место соотношение substr($text,$-[()],$+[О]-$-[0]) эквивалентно $<&, suhstr($text,$-[!],$+[ !]-$-[ 1]) эквивалентно $1 и т. д.
Теперь буду давать пояснения к этому списку. Во-первых, имейте в виду, что переменная $0, похожая на нумерованную, не имеет отношения к регулярным выражениям, а хранит имя сценария Perl, запущенного на выполнение.
Начинающие часто путают специальные переменные 5+ и между которыми имеется тонкое различие. Сначала рассмотрим пример использования переменной 5+. Пусть в регулярном выражении мы имеем альтернативную конструкцию, альтернативы которой заключены в захватывающие скобки:
$text =~ /(...) |(...)| (...)/;
Мы знаем, что совпадение может быть нс более чем с одной альтернативой, и хотим получить фрагмент текста, совпавшего с какой-либо альтернативой. Не будь переменной 5+, нам пришлось бы перебирать переменные $1, 52,... и определять, какая из них имеет определенное значение.
Для понимания отличия переменной 5+ от $*N рассмотрим такой пример:
print u$+^$+, if “abc” =" /(a(bc))/;
На печати окажется строка
$+=bc, $"N=abc
Различие происходит от того, что скобки могут быть вложенными. Нумерованная переменная с наибольшим номером здесь 5*2, а последними закрываются скобки у переменной $1.
Использовать значения переменных 5+ и S^N можно также в коде Perl внутри регулярного выражения. Эти переменные корректируются после того, как закроется очередная захватывающая скобка. Например:
print “$+=$+t $~N=$~N”
if “abed” =“ /(a(bc)(d)(?{ print “$+=$+, $~N=$~N ” }))/;
Здесь выводятся значения переменных $+ и 5ЛЛ' после третьей скобки внутри регулярного выражения, а также после того, как оператор поиска отработал. В итоге получается результат
$+=d, $"N=d
$+=d, $"N=abcd
5+ в обоих случаях относится к нумерованной переменной с максимальным номером — 55, а переменная 5W внутри регулярного выражения копирует переменную 55, а вне регулярного выражения является копией переменной $1.