Условная конструкция
В регулярных выражениях Perl имеется условная конструкция, которая позволяет сделать выбор подобно операторам if... then или if... then... else ... Она имеет такой синтаксис:
(? условие шаблон-да )
или полный вариант
(? условие шаблон-да | шаблон-нет )
Работает эта конструкция так: вначале проверяется условие, и если оно истинно, то вся эта конструкция как бы заменяется на шаблон-да, а если условие ложно, то вместо конструкции подставляется шаблон-нет (если он есть). А если его нет, то на место этой конструкции ничего не подставляется, как будто этой конструкции не было.
После символов (?в реальной программе всегда будет стоять открывающая круглая скобка. Эта скобка не может отделяться пробельными символами от знака вопроса, даже если регулярное выражение записано в свободном формате (с модификатором л).
Шаблон-да и шаблон-нет представляют из себя произвольные регулярные выражения, а условие может иметь следующие значения:
1. Число в круглых скобках. Тогда оно считается номером каких-то захватывающих скобок. Если захватывающие скобки с данным номером участвовали в совпадении, то условие считается истинным, если нет — ложным. Здесь опять повторю замечание, что участвовать в совпадении и иметь непустое значение — не одно и то же. В операторе
" =~ /(-*>/;
скобки участвовали в совпадении, и переменная $1 получила пустое значение. В операторе
" =~ /(?)*/;
скобки не участвовали в совпадении, хотя поиск также завершился удачно. Но т.к. квантификатор имел значение 0. то переменная $1 не существует (имеет неопределенное значение).
В следующем примере отыскивается ссылка href, которая может быть заключена в кавычки, апострофы или не быть ограничена ничем:
my $text=’ Іпіегпеі-обучениеа>';
if ($text ="
m!]*?hrefs*=s*
([“'])? й совпадение для разделителя (', “ или пусто).
й Запоминаем его
- (["” ‘>х20]+) й ссылка (все кроме пробела, ' и «)
- (?(1)1) й если был разделитель, то подставляем шаблон й для него
[”>]?>["<]+а>!ix) ! print $2 }
Обратите внимание, что при появлении квантификатора х изменились ограничители регулярного выражения (с # на ’) и внутри класса символов пробел задан как х20.
2. Позиционная проверка, четыре варианта которой мы рассматривали. Если проверка возвращает истину, то подставляется шаблон-да, иначе подставляется шаблон-нет или «пусто» в случае короткого варианта условной консгрукции.
Для этого случая рассмотрим такой пример: пусть надо обрабатывать десятичные и 16ные числа и пусть 16ные числа предваряются символом $. Программа обработки может быть такой:
$_=’ 1234 ааа $12aF
/(?(?=$|d)
- (
- (?(?=$)
$[da-fA-F]+
(?{ print 'hex
I
d+
(?{ print 'dec
)
(?{ print "$1 ”
[”WJ*
)/gx;
$abc $z 1456’;
И начало числа?
U да, начинаем его захват
И 16-ное число?
U да, подставляем шаблон 16-ного числа
* }) # печатаем префикс hex
ft нет, ставим шаблон 10-ного числа
* }) # печатаем префикс dec
ft конец захвата числа
ft конец вложенного условия
}) ft печатаем само число
ft это не начало числа, пропускаем все до числа
На печать выдается следующее:
dec 1234
hex $12аГ
hex $abc
dec 1456
А теперь разберемся, как работает эта программа. В регулярном выражении имеется две условные конструкции, вторая из них вложена в первую (используется в качестве шаблона-да). Внешняя условная конструкция имеет такую логику: следующий символ — 5 или десятичная цифра? Да — тогда применяем вложенную условную конструкцию. которая разделит десятичные и 16ные числа. Нет — тогда подставим шаблон который быстро пропустит все до следу
ющего числа.
Вложенная конструкция тоже имеет полную форму и работает так: если следующий символ — X то она подставляет шаблон $fda-fA-FJ+, который соответствует 1 биому числу, а иначе подставляет шаблон d+ для десятичного числа.
Кроме того, в первой альтернативе внешней условной конструкции производится захват числа в нумерованную переменную 5/, а после шаблонов для каждого типа чисел выводится на печать, соответст венно, слово hex или dec. После закрывающей захватывающей скобки выводится само число из $1.
Может возникнуть вопрос: как будет обрабатываться фрагмент текста $z, который не является числом, но начинается с символа 5? В этом случае сработает первая альтернатива из внешней условной конструкции, которая подставит шаблон $[cla-fA-FJ+. Он не совпадет с этим фрагментом, а это будет означать, что все регулярное выражение не совпало с данной позицией. Но благодаря модификатору g поиск будет продолжаться в цикле со следующей позиции текста (символа z), и все числа будут напечатаны. Подробнее о работе модификатора g мы будем говорить, когда будем описывать работу операторов т/.../и s/.../.../.
3. Фрагмент кода Perl. Если в качестве условия выступает фрагмент кода Perl, то используется возвращаемое им значение, т.е. результат последнего вычисления. Если он отличен от пустой строки, строки, которая состоит только из числа 0 (0.0), неопределенности и числового нуля, то считается истиной, иначе — ложью. Здесь еще скажу, что в Perl есть интересная специальная переменная $AR — результат последнего выполнения кода Perl в регулярном выражении. Здесь слово «последнего» понимается как результат кода, который выполнился последний раз по времени в ходе работы системы поиска соответствия. Т.е. $AR всегда хранит самый «свежий» результат выполнения встроенного кода Perl. Кроме того, при возврате назад за код Perl вычисленное этим кодом значение «забывается» и восстанавливается предыдущее вычисленное значение, т.е. эта переменная автоматически локализуется. В начале работы программы переменная $AR имеет неопределенное значение, а после выхода из оператора поиска или проверки имеет последнее присвоенное ей значение. Кроме того, код Perl, который стоит в части условия условной конструкции, не изменяет значения переменной $ARl Интересно, что Perl не запрещает присваивать этой переменной значение напрямую.
Задание модификаторов внутри регулярного выражения
Нами уже был рассмотрен вариант расположения модификаторов между знаком вопроса и двоеточием в группирующих скобках. Есть еще один вариант задания модификаторов:
(? модификаторы )
Например. — включение режимов і и s и отключение режи
мов/м их. Область действия этой конструкции начинается сразу после нее и продолжается до следующей закрывающей круглой скобки. Имеется в виді; конечно, «настоящая» скобка, а не литерал ), который эквивалентен кодуг к29. Если справа от этой конструкции нет закрывающей скобки. то ее область действия простирается до конца регулярного выражения. Эта закрывающая скобка может принадлежать захватывающей или незахватывающей паре скобок, закрывать условную конструкцию и т. д. Но. конечно, эту установку модификаторов может отменить другая установка тех же модификаторов. В конечном случае имеет значение та установка модификатора, которая находится «ближе» к данному фрагменту' регулярного выражения.
Атомарная группировка тоже относится к дополнительным конструкциям. но мы ее уже рассмотрели.