В первом, более простом варианте, вы можете использовать специальные скобки
(?# комментарий ).
Эта конструкция игнорируется. Комментарий не может содержать закрывающую круглую скобку, т.к. по ее наличию определяется, где заканчивается конструкция комментария. Сам комментарий может отсутствовать: закрывающая скобка может стоять сразу за решеткой. Конструкция комментария может даже стоять между
print "bb" =~ /^b(?#aaaaa){2}$/;
напечатает единицу. Но это еще не значит, что конструкция комментария может стоять абсолютно в любом месте
Вот еще одна тонкость: если это наше
print "bb" =~ m#^b(?#aaaaa){2}$#;
Возникнет сообщение
Sequence (? incomplete in regex; …
Дело в том, что \x23 ), то он должен быть замаскирован обратной косой чертой:
print "bb" =~ m#^b(?\#aaaaa){2}$#;
Здесь уже все в порядке.
Но это, конечно, запутывает
m( регулярное выражение )
и хотим в этом выражении применять скобочные конструкции. Тогда нам придется маскировать обратным слэшем все круглые скобки! А как в /, то в качестве ограничителей лучше выбирать восклицательный знак, решетку, двоеточие, запятую, знак процента или аналогичный символ, который отсутствует в
Чаще используют запись x. В зоне действия этого
print "bb" =~
/^ # Это начало строки
b # Далее идет символ b
{2} # За ним следует квантификатор
$ # И в конце - конец строки
/x;
И этот пример работает. Как видим, мы включили не только комментарии, но и пробелы для красивых отступов вне комментариев! Да, в пределах действия x все пробельные символы (а не только пробелы) игнорируются. Ведь комментарии надо чем-то отделять для наглядности от кода. Но теперь в
\x20 для пробела \t для табуляции и т.д.
Или же в общем виде: \s.
Мы уже применяли захватывающие и просто группирующие скобки. Рассмотрим еще некоторые тонкости.
Как работают группирующие скобки с $1 скобки в 'abc' =~ /(\w)*/? Это выражение похоже на (\w*), которое в переменную $1 захватит все три символа, но алгоритм его работы иной. Скобки в (\w)* захватят последний символ - c. Для тех, кто впервые с этим сталкивается, это кажется непонятным. Это работает так: сначала \w совпадет с буквой a, затем * будет заставлять повторяться всю внутрискобочную конструкцию снова и снова, насколько это возможно, оставляя при этом сохраненные состояния. При возвратах, когда происходит выход за открывающую
В нашем случае выражение \w повторится трижды, захватывая каждый раз следующую букву, и в конце концов захваченной окажется буква c. Мы получаем интересный тактический прием захвата последнего фрагмента текста, который соответствует заданному
/(\w)*\w/
А как бы стал работать этот
'abc' =~ /(\w)*?/;
скобки бы совпали с пустым фрагментом в начале строки, а переменная $1 получила бы неопределенное значение. Ее попросту не было бы ввиду нулевого значения
'abc' =~ /(\w*?)/;
то переменная $1 существовала бы и имела бы пустое значение.
Теперь рассмотрим несохраняющие (группирующие) скобки:
(?: шаблон )
Такие скобки, как мы знаем, не создают
(?im:^passport nr\. \d+)
Область действия этих ^ будет совпадать не только в начале текста, но также в начале каждой логической строки, т.е. сразу после символа \n, если только он не стоит самым последним в тексте. Но, конечно, эти режимы могут быть отменены другими
Аналогично можно отменить действие
(?-i:^passport nr\. \d+)
Поиск будет вестись с учетом регистра символов. Или
(?i-ms:^passport nr\. \d+)
Включается i и отключаются m и s.
И в конце добавлю, что скобки, как и другие \x3a вместо (. Но! Забегая вперед, скажу, что почти произвольные части
my $a='(';
'abc' =~ /$a\w)*/;
print $1;
На печать выйдет символ c. Этот не описанный в руководствах способ работает потому, что интерполяция переменных в
Это сложное условие (
(?= шаблон )
\b, \A, $ и т.д.
Замечу, что
(?> шаблон ) эквивалентно (?=( шаблон ))\1
Происходит это потому, что после выполнения опережающей (как и ретроспективной) проверки уничтожаются все сохраненные состояния, возникшие внутри нее.
Имеется противоположный случай проверки - негативная опережающая проверка:
(?! шаблон )
Такое условие истинно, если в текущей позиции нет текста, совпадающего с заданным
Например,
\w+(?=\s+)
найдет слово, за которым стоит один или несколько пробельных символов, но сами пробельные символы в результат поиска не войдут. Дело в том, что позиционная проверка не поглощает текст: после применения этих условных конструкций текущая позиция в тексте вернется на прежнее место, где была до применения этого
Рассмотрим такой пример:
$_='abc'; print "1\n" if /a(?=(b))bc/; print $1;
Будут напечатаны такие строки:
1 b
Как видим, после совпадения с символом a после него ищется символ b. Он находится, и поиск продолжается дальше. Если сразу бы после a не стоял символ b, то поиск потерпел бы неудачу и началась бы следующая итерация, т.к. сохраненных состояний, к которым можно вернуться, нет. Внутри опережающей проверки этот символ захватывается в переменную $1, после чего проверка заканчивается успешно, и текущая позиция в строке возвращается к символу b. Затем выполняется соответствие bc символам bc, на этом оператор поиска успешно завершается.
Подобные сложные проверки бывают необходимы в сложных случаях, когда надо принять решение в зависимости от того, какой фрагмент текста находится в текущей позиции (или вообще впереди нее). Эти условия обычно используются в условных конструкциях, о которых речь впереди.
Обратите внимание на интересную особенность сложных условий: в результате работы оператора
"a" =~ /(?=(a))/
переменная $1 получит значение a, а в результате работы похожего
"a" =~ /((?=a))/
переменная $1 получит пустое значение. Это можно объяснить тем, что в первом случае внутри сложного условия происходит захват буквы a, а затем после выхода за это сложное условие (на конец a, но сама буква уже сидит в переменной $1. Во втором случае после выполнения фрагмента ((?=a текущая позиция в a, но после закрытия скобки в сложном условии ((?=a) происходит возврат текущей позиции в а, и после закрытия a, как и в момент открытия захватывающей пары скобок. В результата эта пара скобок захватывает пустой фрагмент текста.
Имеется аналогичная возможность также "заглянуть назад":
(?<= шаблон )
Это условие истинно, если перед текущей позицией имеется текст, совпадающий с
$_='abcd'; print "1\n" if /ab(?<=(ab))/; print $1;
В результате получим вывод
1 ab
Как видим, захват текста в этих
Негативная ретроспективная проверка задается выражением
(?<! шаблон )
и требует, чтобы непосредственно перед текущей позицией не было текста, соответствующего данному
Но в ретроспективных проверках
Иначе пришлось бы искать с начала всего текста, а это большие непроизводительные затраты времени. Поэтому шаблон не может содержать
(?<=\w+)
(?<=\w{1,2})
(?<=\w{3}|abcd)
В первых двух случаях имеем переменную длину
В качестве примера использования этих 12,345,678. Хотя тройки разрядов отсчитываются справа, а механизм поиска просматривает текст слева, эту техническую сложность нетрудно обойти. Сформулируем условие вставки запятой так: запятая вставляется в позицию, слева от которой имеется цифра, а справа - произвольное ненулевое число групп из трех цифр и далее не стоит цифра. Вот программа, которая моделирует этот пример:
$_='number 1: 12345678 number 2: 98765432154321';
s/(?<=\d)(?=(?:\d{3})+(?!\d))/,/g;
print $_;
На печать выведется
number 1: 12,345,678 number 2: 98,765,432,154,321
Вторая проверка здесь сложная: она включает в себя еще одну проверку того, что дальше не стоит цифра. g обеспечивает расстановку запятых по всему тексту в нужных местах.
Если бы мы вынесли за скобку проверку (?!\d) и написали бы так:
s/(?<=\d)(?=(?:\d{3})+)(?!\d)/,/g;
то это было бы неправильно. Смысл получился бы таким: позиция, перед которой стоит цифра, за которой идет группа из троек цифр и за которой нет цифры. Этот набор условий никогда не выполняется.
Благодаря тому, что позиционные проверки не поглощают текст, для данной позиции текста можно записать сколько угодно таких проверок. Все они должны выполняться, иначе произойдет локальная неудача поиска. Например:
/(?=\d)(?![09])/;
означает, что в этой позиции должна стоять цифра и она не должна быть равна нулю и девяти. Это равносильно условию
/(?=[1-8])/;
Ко всему сказанному добавлю, что к позиционным проверкам, как и вообще к условиям с нулевой длиной совпадения, нельзя ставить
Встроенный код next, last, break, redo, goto и вызовы подпрограмм - это не предусмотрено правилами, хотя транслятор за этим не следит. Не следут также использовать во встроенном коде операторы, в которые входят
Также не пытайтесь изменять во встроенном коде результирующий текст - это не даст эффекта.
Иногда вы можете обнаружить, что код
'abc' =~ /(?{ print '123' })abcd/;
Система поиска определит, что для совпадения длина результирующего текста должна быть не меньше четырех символов, а их в тексте только три. Оператор закончится неудачно без применения поиска по
Мы уже знаем, как выглядит конструкция вставки кода
(?{ код Perl })
Подробнее о встроенном коде мы поговорим в дальнейшем, когда наберемся опыта.
В if … then или if … then … else … Она имеет такой синтаксис:
(? условие шаблон-да )
или полный вариант
(? условие шаблон-да | шаблон-нет )
Работает эта конструкция так: вначале проверяется условие, и если оно истинно, то вся эта конструкция как бы заменяется на шаблон-да, а если условие ложно, то вместо конструкции подставляется шаблон-нет (если он есть). А если его нет, то на место этой конструкции ничего не подставляется, как будто этой конструкции не было.
После символов (? в реальной программе всегда будет стоять открывающая круглая скобка. Эта скобка не может отделяться пробельными символами от знака вопроса, даже если x ).
Шаблон-да и шаблон-нет представляют из себя произвольные
'' =~ /(.*)/;
скобки участвовали в совпадении и переменная $1 получила пустое значение. В операторе
'' =~ /(.)*/;
скобки не участвовали в совпадении, хотя поиск также завершился удачно. Но т.к. 0, то переменная $1 не существует (имеет неопределенное значение).
В следующем примере отыскивается ссылка href, которая может быть заключена в кавычки, апострофы или не быть ограничена ничем:
my $text='<a target="_blank" href="http://www.intuit.ru/">Internet-обучение</a>';
if ($text =~
m!<a\s+[^>]*?href\s*=\s*
(["'])? # совпадение для разделителя (', " или пусто). Запоминаем его
([^"'>\x20]+) # ссылка (все кроме пробела, ' и ")
(?(1)\1) # если был разделитель, то подставляем шаблон для него
[^>]*>[^<]+</a>!ix) { print $2 }
Обратите внимание, что при появлении \x20.
да, иначе подставляется нет или "пусто" в случае короткого варианта условной конструкции.Для этого случая рассмотрим такой пример: пусть надо обрабатывать десятичные и 16-ные числа и пусть 16-ные числа предваряются символом $. Программа обработки может быть такой:
$_=' 1234 aaa $12aF $abc $z 1456';
/(?(?=\$|\d) # начало числа?
( # да, начинаем его захват
(?(?=\$) # 16-ное число?
\$[\da-fA-F]+ # да, подставляем шаблон 16-ного числа
(?{ print 'hex ' }) # печатаем префикс hex
|
\d+ # нет, ставим шаблон 10-ного числа
(?{ print 'dec ' }) # печатаем префикс dec
) # конец захвата числа
) # конец вложенного условия
(?{ print "$1\n" }) # печатаем само число
[^\$\d]* # это не начало числа, пропускаем все до числа
)/gx;
На печать выдается следующее:
dec 1234 hex $12aF hex $abc dec 1456
А теперь разберемся, как работает эта программа. В да ). Внешняя условная конструкция имеет такую логику: следующий символ - $ или десятичная цифра? Да - тогда применяем вложенную условную конструкцию, которая разделит десятичные и 16-ные числа. Нет - тогда подставим [^\$\d]*, который быстро пропустит все до следующего числа.
Вложенная конструкция тоже имеет полную форму и работает так: если следующий символ - $, то она подставляет шаблон \$[\da-fA-F]+, который соответствует 16-ному числу, а иначе подставляет шаблон \d+ для десятичного числа.
Кроме того, в первой альтернативе внешней условной конструкции производится захват числа в $1, а после hex или dec. После закрывающей $1.
Может возникнуть вопрос: как будет обрабатываться фрагмент текста $z, который не является числом, но начинается с символа $? В этом случае сработает первая альтернатива из внешней условной конструкции, которая подставит \$[\da-fA-F]+. Он не совпадет с этим фрагментом, а это будет означать, что все g, поиск будет продолжаться в цикле со следующей позиции текста (символа z ), и все числа будут напечатаны.
Подробнее о работе g мы будем говорить, когда будем описывать работу операторов m/…/ и s/…/…/.
0 (0.0), неопределенности и числового нуля, то считается истиной, иначе ложью. Здесь еще скажу, что в $^R - результат последнего выполнения кода $^R всегда хранит самый "свежий" результат выполнения встроенного кода $^R имеет неопределенное значение, а после выхода из оператора поиска или проверки имеет последнее присвоенное ей значение. Кроме того, код $^R! Интересно, что Нами уже был рассмотрен вариант расположения
(? модификаторы )
Например, (?is-mx) - включение режимов i и s и отключение режимов m и x. Область действия этой конструкции начинается сразу после нее и продолжается до следующей закрывающей круглой скобки. Имеется в виду, конечно, "настоящая" скобка, а не литерал \), который эквивалентен коду \x29. Если справа от этой конструкции нет закрывающей скобки, то ее область действия простирается до конца
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.