¬ведение в регул€рные выражени€. —интаксис

“ут ремонт iphone 8 plus делают опытные мастера.

¬ведение в регул€рные выражени€. —интаксис.

PHP отличаетс€ наличием очень мощных и гибких механизмов дл€ работы с двум€ самыми часто используемыми типами данных: строками и массивами. ќб этом мы говорили в одном из предыдущих выпусков. ќднако в PHP есть еще один механизм обработки строк, который, ввиду своей сложности и мощи был пропущен мною. я говорю о механизме регул€рных выражений (regular expressions). Ќастало врем€ поговорить о них, потому что в дальнейшем нам очень часто потребуетс€ использовать их.  роме того использование регул€рных выражений во многих ситуаци€х поможет вам заменить кучу кода всего одной строчкой. ≈динственна€ проблема, котора€ обычно возникает при работе с регул€рными выражени€ми - их очень необычный, и, поначалу, совершенно непон€тный синтаксис. ѕоэтому € постараюсь рассказать о синтаксисе регул€рных выражений по возможности более просто и подробно.

–егул€рные выражени€

ќбща€ информаци€

–егул€рное выражение (regular expression, regexp, регэксп) - механизм, позвол€ющий задать шаблон дл€ строки и осуществить поиск данных, соответствующих этому шаблону в заданном тексте.  роме того, дополнительные функции по работе с regexp'ами позвол€ют получить найденные данные в виде массива строк, произвести замену в тексте по шаблону, разбиение строки по шаблону и т.п. ќднако главной их функцией, на которой основаны все остальные, €вл€етс€ именно функци€ поиска в тексте данных, соответствующих шаблону, описанному в синтаксисе регул€рных выражений.

ќчень часто регул€рные выражени€ используютс€ дл€ того, чтобы проверить, €вл€етс€ ли данна€ строка строкой в необходимом формате. Ќапример следующий regexp предназначен дл€ проверки того, что строка содержит корректный e-mail адрес:

/^\w+([\.\w]+)*\w@\w((\.\w)*\w+)*\.\w{2,3}$/

¬ыгл€дит, на первый взгл€д, довольно страшно :-) Ќо, тем не менее, это работает, и работает очень хорошо. ј когда вы научитесь писать и использовать regexp'ы в своем коде - это еще будет и сильно облегчать вам жизнь.

–егул€рные выражени€ пришли к нам из Unix и Perl. ¬ PHP существует два различных механизма дл€ обработки регул€рных выражений: POSIX-совместимые и Perl-совместимые. »х синтаксис во многом похож, однако Perl-совместимые регул€рные выражени€ более мощные и, к тому же, работают намного быстрее (в некоторых случа€х до 10 раз быстрее). ѕоэтому здесь мы будем вести речь только о Perl-совместимых регул€рных выражени€х.  стати, необходимо заметить, что полное описание синтаксиса регул€рных выражений, имеющеес€ в PHP Manual, занимает более 50 килобайт и, естественно, здесь мы не будем рассматривать весь синтаксис. Ќам необходимы только основы, которые помогут вам пон€ть, как именно пишутс€ регул€рные выражени€.

—утью механизма регул€рных выражений €вл€етс€ то, что они позвол€ют задать шаблон дл€ нечеткого поиска по тексту. Ќапример, если перед вами стоит задача найти в тексте определенное слово, то с этой задачай хорошо справл€ютс€ и обычные функции работы со строками. ќднако если вам нужно найти "то, не знаю что", о чем вы можете сказать только то, как приблизительно это должно выгл€деть - то здесь без регул€рных выражений просто не обойтись. Ќапример, вам необходимо найти в тексте информацию, про которую вам известно только то, что это "3 или 4 цифры после которых через пробел идет 5 заглавных латинских букв", то вы сможете сделать это очень просто, возпользовавшись следующим регул€рным выражением:

/\d{3,4}\s[A-Z]{5}/
—интаксис регул€рных выражений

–егул€рные выражени€, как уже было сказано выше, представл€ют собой строку. —трока всегда начинаетс€ с символа разделител€, за которым следует непосредственно регул€рное выражение, затем еще один символ разделител€ и потом необ€з€тельный список модификаторов. ¬ качестве символа разделител€ обычно используетс€ слэш ('/'). “аким образом в следующем регул€рном выражении: /\d{3}-\d{2}/m, символ '/' €вл€етс€ разделителем, строка '\d{3}-\d{2}' - непосредственно регул€рным выражением, а символ 'm', расположенный после второго разделител€ - это модификатор.

ќсновой синтаксиса регул€рных выражений €вл€етс€ тот факт, что некоторые символы, встречающиес€ в строке рассматриваютс€ не как обычные символы, а как имеющие специальное значение (т.н. метасимволы). »менно это решение позвол€ет работать всему механизму регул€рных выражений.  аждый метасимвол имеет свою собственную роль в синтаксисе регул€рных выражений. ƒалее мы рассмотрим все эти метасимволы.

ќдним из самых важных метасимволов €вл€етс€ символ обратного слэша ('\'). ≈сли в строке встречаетс€ этот символ, то парсер рассматривает символ, непосредственно следующий за ним дво€ко:

  • если следующий символ в обычном режиме имеет какое-либо специальное значение, то он тер€ет это свое специальное значение и рассматриваетс€ как обычный символ. Ёто совершенно необходимо дл€ того, чтобы иметь возможность вставл€ть в строку специальные символы, как обычные. Ќапример метасимвол '.', в обычном режиме означает "любой единичный символ", а '\.' означает просто точку. “акже можно лишить специального значени€ и сам этот символ: '\\'.
  • если следующий символ в обычном режиме не имеет никакого специального значени€, то он может получить такое значение, будучи соединенным с символом '\'.   примеру символ 'd' в обычном режиме воспринимаетс€ просто как буква, однако, будучи соединенной с обратным слэшем ('\d') становитс€ метасимволом, означающим "люба€ цифра".

—уществует множество символов, которые образуют метасимволы в паре с обратным слэшем.  ак правило подобные пары используютс€ дл€ того, чтобы показать, что на этом месте в строке должен находитьс€ символ, с кодом, который не имеет соответствующего ему изображени€ или же символ, принадлежащий какой-то определенной группе символов. Ќиже приведены некоторые наиболее употребительные:

 ћетасимвол  «начение
ћетасимволы дл€ задани€ символов, не имеющих изображени€
\n —имвол перевода строки (код 0x0A)
\r —имвол возврата каретки (код 0x0D)
\t —имвол табул€ции (код 0x09)
\xhh ¬ставка символа с шестнадцатиричным кодом 0xhh, например \x41 вставит латинскую букву 'A'
ћетасимволы дл€ задани€ групп символов
\d ÷ифра (0-9)
\D Ќе цифра (любой символ кроме символов 0-9)
\s ѕустой символ (обычно пробел и символ табул€ции)
\S Ќепустой символ (все, кроме символов, определ€емых метасимволом \s)
\w "—ловесный" символ (символ, который используетс€ в словах. ќбычно все буквы, все цифры и знак подчеркивани€ ('_'))
\W ¬се, кроме символов, определ€емых метасимволом \w

— остальными имеющимис€ метасимволами, построенными по этому принципу вы при желании сможете ознакомитьс€ в оригинальном описании.

ѕриведу несколько простейших примеров дл€ того, чтобы вы понимали, о чем идет речь. —разу оговорюсь, что примеры несколько громоздки и некрасивы, но лишь потому, что € не стал использовать в них метасимволы, о которых еще не рассказал и которые сделали бы их намного проще.

Regexp  омментарии
/\d\d\d/ Ћюбое трехзначное число ('123', '719', '001')
/\w\s\d\d/ Ѕуква, пробел (или табул€ци€) и двузначное число ('A 01', 'z 45', 'S 18')
/\d and \d/ Ћюба€ из следующих строк: '1 and 2', '9 and 5', '3 and 4'.

—интаксис регул€рных выражений имеет средства дл€ определени€ собственных подмножеств символов. Ќапример вам может понадобитьс€ задать условие, что в этом месте строки должна находитьс€ шестнадцатирична€ цифра или еще что-то подобное. ƒл€ описани€ таких подмножеств примен€ютс€ символы квадратных скобок '[]'.  вадратные скобки, встреченные внутри регул€рного выражени€ считаютс€ одним символом, который может принимать значени€, перечисленные внутри этих скобок.

≈сть небольша€ тонкость в том, как работают метасимволы внутри квадратных скобок. ƒело в том, что в синтаксисе регул€рных выражений существует еще множество метасимволов, но практически все они работают только вне секций описаний подмножеств. ≈динственные метасимволы, которые работают внутри этих секций это:

  • ќбратный слэш ('\'). “.е. все метасимволы из приведенной ранее таблицы будут работать.
  • ћинус ('-'). »спользуетс€ дл€ задани€ набора символов из одного промежутка (например все цифры могут быть заданы как '0-9')
  • —имвол '^'. ≈сли этот символ стоит первым в секции задани€ подмножества символов (и только в этом случае!) он будет рассматриватьс€ как символ отрицани€. “.о. можно задать все сиволы, которые не описаны в данной секции.

Ќесколько примеров, чтобы было пон€тно, как это работает:

Regexp  омментарии
[0-9A-Fa-f] ÷ифра в шестнадцатиричной системе счислени€
[\dA-Fa-f] “о же самое, но с использованием метасимвола
[02468] „етна€ цифра
[^\d] ¬се, кроме цифр (аналог метасимвола \D)
[a^b] Ћюбой из символов 'a', 'b', '^'. «аметьте, что здесь символ '^' не имеет какого-либо специального значени€, потому что стоит не на первой позиции внутри квадратных скобок.

“еперь необходимо рассмотреть еще несколько метасимволов.  ак уже было сказано ранее, все они работают только вне секций описчаний подмножеств символов (вне квадратных скобок).

—имволы '^' и '$'. ќни использутс€ дл€ того, что того, чтобы указать парсеру регул€рных выражений на то, чтобы он обратил внимание на положение искомого текста в строке. —имвол '^' указывает, что искомый текст должен находитьс€ в начале строки, символ '$' наоборот, указывает, что искомый текст должен находитьс€ в конце строки. ѕосмотрим, как это работает на примере:

ƒопустим, у нас есть текст:

12 aaa bbb
aaa 27 ccc
aaa aaa 45

» регул€рное выражение дл€ поиска чисел в этом тексте: /\d\d/m (не обращайте пока внимани€ на модификатор). ѕоиск по этому регул€рному выражению вернет нам 3 значени€: '12', '27', '45'. “еперь ограничим поиск, указав, где именно внутри строки должен располагатьс€ текст: /^\d\d/m. «десь результат будет только один - '12', потому что только это число располагаетс€ в начале строки. јналогично, регул€рное выражение /\d\d$/m вернет результат '45'.

—имвол точки '.'. Ётот метасимвол указывает, что на данном месте в строке может находитьс€ любой символ (за исключением символа перевода строки). ќчень удобно использовать его, если вам нужно "пропустить" какую-нибудь букву в слове при проверке. Ќапример регул€рное выражение /.bc/ найдет в тексте и 'abc' и 'Abc' и 'Zbc' и '5bc'.

—имвол вертикальной черты ' '. »спользуетс€ дл€ задани€ списка альтернатив. Ќапример регул€рное выражение:

/(красное зеленое) €блоко/

Ќайдет в тексте все словосочетани€ 'красное €блоко' и 'зеленое €блоко'. ќ значении круглых скобок в этом выражении см. далее.

—имволы круглых скобок '(' и ')'. Ёти символы позвол€ют получить из искомой строки дополнительную информацию. ќбычно, если парсер регул€рных выражений ищет в тексте информацию по заданному выражению и находит ее - он просто возвращает найденную строку. ќднако, если он встречает внутри регул€рного выражени€ круглые скобки, то он рассматривает содержимое этих скобок как еще одно регул€рное выражение, по которому необходимо произвести поиск. ѕарсер рекурсивно вызывает сам себ€ дл€ поиска по новому регул€рному выражению и использует результаты поиска дл€ дальнейшей обработки основного регул€рного выражени€. ѕри этом, если поиск хот€ бы по одному из внутренних регул€рных выражений не увенчалс€ успехом - поиск по всему регул€рному выражению считаетс€ безуспешным.

„тобы было пон€тнее, о чем € только что рассказал - рассмотрим в качестве примера то, как работает парсер регул€рных выражений в случае приведенного выше регул€рного выражени€ о €блоках: /(красное зеленое) €блоко/.

  1. ѕарсер начинает разбор регул€рного выражени€ и встречает выражение в скобках: (красное зеленое)
  2. ѕарсер вызывает себ€ дл€ поиска по найденному регул€рному выражению
  3. ѕолучив результаты поиска парсер подставл€ет по очереди каждый из полученных результатов на место выражени€ в скобках и смотрит, удовлетвор€ет ли найденный результат всем услови€м основного регул€рного выражени€ (в данном случае смотрит, есть ли после найденного слова слово "€блоко").
  4. ≈сли все в пор€дке - результаты поиска по каждому из имеющихс€ регул€рных выражений дл€ этого случа€ возвращаютс€, если нет - парсер просто переходит к следующему найденному фрагменту. –езультат поиска внутреннего регул€рного выражени€ дл€ этого фрагмента при этом тер€етс€.

¬ качестве примера возьмем строку:

€блоко красное и зеленое €блоко и еще одно красное €блоко и еще одно €блоко, зеленое

ѕоиск по внутреннему регул€рному выражению даст 4 результата (выделены жирным шрифтом):

€блоко красное и зеленое €блоко и еще одно красное €блоко и еще одно €блоко, зеленое

ќднако поиск по всему регул€рному выражению даст всего 2 результата, потому как в остальных случа€х услови€ основного регул€рного выражени€ не выполн€ютс€:

€блоко красное и зеленое €блоко и еще одно красное €блоко и еще одно €блоко, зеленое

Ќеобходимо заметить, что дл€ этих двух случаев будет возвращен не только результат поиска по основному регул€рному выражению, но и результат поиска по внутреннему регул€рному выражению дл€ каждого из найденных фрагментов. ¬ большинстве случаев это полезно (пример - чуть позднее), но иногда наоборот, лучше избавитьс€ от лишних результатов. ¬ этом случае необходимо добавить символы '?:' непосредственно после открывающейс€ круглой скобки: /(?:красное зеленое) €блоко/.

“еперь пример, когда получение результатов внутренних регул€рных выражений может быть полезным. ƒопустим, нам необходимо проверить, €вл€етс€ ли строка семизначным телефонным номером с указанием кода города и получить из нее код города и номер телефона:

/\((\d{3,5})\)\s+(\d{3}-\d{2}-\d{2})/

Ќекоторые из примененных здесь метасимволов вам еще неизвестны и будут рассмотрены чуть позднее. ƒавайте рассотрим этот regexp подробнее.

ѕерва€ кругла€ скобка здесь тер€ет свое специальное значение и будет рассматриватьс€ как обычный символ:

/\((\d{3,5})\)\s+(\d{3}-\d{2}-\d{2})/

ƒалее идет регул€рное выражение в скобках (проверка кода города):

/\((\d{3,5})\)\s+(\d{3}-\d{2}-\d{2})/

ѕосле этого идет закрывающа€ кругла€ скобка, котора€ также лишена своего специального значени€ из-за символа обратного слэша, сто€щего перед ней:

/\((\d{3,5})\)\s+(\d{3}-\d{2}-\d{2})/

«атем идет пропуск пустого места:

/\((\d{3,5})\)\s+(\d{3}-\d{2}-\d{2})/

» еще одно регул€рное выражение в скобках, которое провер€ет номер телефона:

/\((\d{3,5})\)\s+(\d{3}-\d{2}-\d{2})/

 ак видите, здесь есть 3 регул€рных выражени€ - основное и два внутренних. ѕри этом основное выражение позвол€ет нам проверить, имеет ли строка необходимый нам формат, а два внутренних - получить соответственно код города и номер телефона. “.е. одним регул€рным выражением мы можем решить сразу несколько задач!

ѕосмотрим, как работает это регул€рное выражение. ѕусть у нас есть строка: "My phone is (095) 123-45-67". –езультатами поиска будут 3 строки: '(095) 123-45-67', '095' и '123-45-67'.

Ќам осталось рассмотреть еще одну группу метасимволов, определ€ющих количественные показатели (т.н. quantifiers).  ак вы уже могли заметить ранее - очень часто бывает необходимо указать, что какой-то символ должен повтор€тьс€ определенное количество раз.  онечно, можно просто указать его необходимое количество раз непосредственно в строке, но это, естественно не выход. “ем более, что очень часто встречаютс€ ситуации, когда точное количество символов неизвестно. ѕоэтому синтаксис регул€рных выражений содержит набор метасимволов, предназначенных именно дл€ решени€ подобных задач.  аждый из описанных ниже метасимволов определ€ет количественную характеристику символа который находитс€ непосредственно перед ним.

«вездочка '*'. ”казывает, что символ должен быть повторен 0 или более раз (т.е. символ может отсутствовать или присутствовать в любых количествах). ѕример: выражение /ab*c/ найдет строки 'ac', 'abc', 'abbc' и т.д.

ѕлюс '+'. ”казывает, что символ должен быть повторен 1 или более раз (т.е. символ об€зан присутствовать и может присутствовать в любых количествах). ѕример: выражение /ab+c/ найдет строки 'abc', 'abbc', 'abbbc' и т.д., но не найдет строку 'ac'.

«нак вопроса '?'. ”казывает, что символ моет как присутствовать, так и нет, но при этом не может повтор€тьс€ более одного раза. ѕример: выражение /ab?c/ найдет строки 'ac' и 'abc', но не найдет строку 'abbc'.

‘игурные скобки '{' и '}'. ќпредел€ют количественную характеристику символа. ¬нутри скобок через зап€тую перечисл€ютс€ минимальное и максимальное количество повторений символа. ѕри этом любой из параметров может быть опущен, а кроме того можно задать точное количество повторений, указав только одно число. ѕримеры:

  • {2,4} - символ долен повторитьс€ минимум 2 раза, но не более 4.
  • {,5} - символ может отсутствовать (т.к. не задано минимальное количество повторений), но если присутствует, то не должен повтор€тьс€ более 5 раз.
  • {3,} - символ должен повтор€тьс€ минимум 3 раза, но может быть и больше.
  • {4} - символ должен повтор€тьс€ ровно 4 раза

≈сть еще одна тонкость в использовании метасимвола '?'. ѕосмотрите на такое выражение: /.+a/. ќжидаетс€, что оно вернет нам часть текста до первого вхождени€ символа 'a' в этот текст. Ќа самом деле оно будет работать несколько не так, как ожидаетс€ и результатом поиска будет весь текст до последнего вхождени€ символа 'a'. ƒело в том, что по умолчанию количественные метасимволы "жадничают" и пытаютс€ захватить как можно больший кусок текста. ≈сли это не нужно (как а нашем случае), то необходимо "отучить" их от жадности, указав знак '?' после количественного метасимвола: /.+?a/. ѕосле этого выражение будет работать так как надо.

ћодификаторы регул€рных выражений

 ак уже было сказано ранее - механизм регул€рных выражений позвол€ет добавл€ть модификаторы, вли€ющие на обработку регул€рного выражени€. Ќиже рассмотрены наиболее употребительные, об остальных вы можете прочитать в оригинальном описании.

ћодификатор «начение
i ¬ключение режима case-insensitive, т.е. большие и маленькие буквы в выражении не различаютс€.
m ”казывает на то, что текст, по которому ведетс€ поиск, должен рассматриватьс€ как состо€щий из нескольких строк. ѕо умолчанию механизм регул€рных выражений рассматривает текст как одну строку вне зависимости от того, чем она €вл€етс€ на самом деле. —оответственно метасимволы '^' и '$' указывают на начало и конец всего текста. ≈сли же этот модификатор указан, то они будут указывать соответственно на начало и конец каждой строки текста.
s ѕо умолчанию метасимвол '.' не включает в свое определение символ перевода строки. “.е. дл€ многострочного текста выражение /.+/ вернет только первую строку, а не весь текст, как ожидаетс€. ”казание этого модификатора снимает это ограничение.
U ƒелает все количественные метасимволы "не жадными" по умолчанию (про "жадность" количественных метасимволов см. выше)

«аключение

Ќа этом мы заканчиваем рассмотрение синтаксиса регул€рных выражений, но тема еще не закончена. ¬ следующем выпуске мы рассмотрим вопросы того, как PHP работает с регул€рными выражени€ми, а также рассмотрим некоторые практические примеры использовани€ регул€рных выражений в ваших программах.


Jurhen aka ёрий —таршинов
webcorp.ru



ѕри перепечатке информации делайте, пожалуйста, ссылку на наш сайт (либо поделитьс€ вконтакте, гугл+ или делитесь в одноклассниках статьЄй). —пасибо!

»сточник: www.wr-script.ru©, 2004-2023г.

ƒелитесь с друзь€ми в соцсет€х. јктивные комментаторы получают свежие скрипты и бесплатные доработки от WR-Script.ru!

¬ернутьс€ к стать€м помощи WEB-мастеру

WR-–°—З—С—В—З–Є–Ї