Главное меню:



Satus — это простая CMS
Комментарии:
    25.12.11 18:13 Написал(а) Селиван (из города Северное)
Хороший блог, однако стоит больше добавлять информации
читать статью »
    10.12.11 16:52 Написал(а) Вася (из города Белгород)
хА. приколько
читать статью »
    29.11.11 13:35 Написал(а) Марианна (из города Кулебаки)
Есть моменты, когда все удается, не ужасайтесь - это пройдет.
читать статью »
    09.11.11 19:12 Написал(а) Капитон (из города Кадуй)
Да, действительно. Так бывает. Можем пообщаться на эту тему.
читать статью »

 
Регулярные выражения

Что такое регулярные выражения, зачем они нужны?.. в этой статье я попробую просто и доступно объяснить, что это такое, не вдаваясь в сложные и непонятные подробности.. как показала практика обучения, понимание вещей у каждого своё, поэтому повествование буду вести исключительно на примерах.. :-)

 

 

Регулярные выражения (англ. regular expressions, regexp, regex) — это формальный язык поиска и осуществления манипуляций с подстроками в тексте, основанный на использовании метасимволов. По сути это строка-образец (паттерн, шаблон, маска), состоящая из символов и метасимволов и задающая правило поиска.

 

Где они используются, спросите вы?.. в принципе много где: веб-серверы (Apache), серверы баз данных (Oracle,  MySql, MsSql и т.п.), языки программирования (Perl, Php, Javascipt, C#, Java и т.п.), текстовые редакторы (MS Word и т.п.), поисковые машины (как локальные, так и интернет-поисковики) -- вобщем везде, где нужна быстрая обработка текста..

 

Синтаксис регулярных выражений везде один, различие только в именах функций вызова разборщика (парсера) регулярных выражений.. Поэтому будем изучать регулярные выражения применительно к php..

 

 

Например, есть строка 03-Jan-2009, являющейся англоязычной записью даты, и нам нужно из этой строки извлечь день, месяц и год. Используя регулярные выражения это сделать несложно (пример на php):

$A = "03-Jan-2009"; // исходная строка

if(preg_match("/^(\d+)-(\w+)-(\d{3,})$/i", $A, $p)){

// теперь в массиве $p  у нас будет следующие данные

// $p[0]  =  03-Jan-2009  -- полное соответствие паттерна (шаблона) исходной строке

// $p[1]  =  03    -- часть исходной строки, соответствующая 1ой скобке паттерна

// $p[2]  =  Jan   -- часть исходной строки, соответствующая 2ой скобке паттерна

// $p[3]  =  2009  -- часть исходной строки, соответствующая 3ой скобке паттерна

}else{

// неверная строка

}

 

теперь подробнее.. выражение /^(\d+)-(\w+)-(\d{3,})$/i внутри функции preg_match называется паттерном (шаблоном, маской поиска): часть паттерна (точнее часть исходной строки, соответствующая части паттерна), заключенная в скобки (...) сохраняется как отдельный элемент массива -- первая скобка как 1ый элемент, 2ая скобка как 2ой элемент и т.д. 

выражение \d указывает разборщику (парсеру) регулярных выражений, что в этом месте должны быть цифры.. это так называемые метасимволы, есть следующие их разновидности:

  \d  --  цифры,

  \D  --  не цифры,

  \w  --  буквы латинницы или символ подчеркивания,

  \W  --  не буквы латинницы или подчеркивание,

  \s  --  пробел, табуляция, переход на другую строку,

  \S  --  не пробел или табуляция, или переход на другую строку,

  [  ]  --  набор символов, например, [abcd]  укажет набор из 4 символов a, b, c, d..

через символ - (минус) можно указывать диапазон символов, пример выше можно переписать как:  [a-d]

для того чтобы в наборе указать символ минуса или скобок, нужно их экранировать слешем, например:  [\-\[\]]

  [^  ]  --  исключающий набор символов, например, [^abcd]  указывает набор всех символов ansi, исключая a, b, c, d..

  . (точка)  --  любой символ..

 

символ + в выражении \d+ означает что будет 1 или более символов отвечающих маске \d.. это так называемый квантификатор, он указывает сколько соответствий нужно искать, есть следующие разновидности:

  +  --  одно или более совпадений,

  ?  --  одно или ноль,

  *  --  ноль или любое количество,

  {N, M}  --  количество совпадений от N до M,

  {N,}  --  количество совпадений от N и более.. например выражение \d{3,} в нашем паттерне указывает, что подряд должно идти 3 или более символов-цифр..

  {, M}  --  количество совпадений от 0 до M,

  {N}  --  количество совпадений равное N ..

есть некоторые хитрые сочетания квантификаторов, о которых в кратце скажу ниже...

 

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

  i  -- без учета регистра,

  s  -- метасимвол . (точка) определяет также переходы на другую строку, без этого можификатора все паттерны рассматриваются в пределах одной строки,

  u  --  паттерны рассматриваются как записанные в кодировке utf-8..

 

p.s.: при использовании функции php preg_replace(...) доступен модификатор e указывающий, что в заменяющей строке присутствует php-код, который нужно выполнить.. но использование такого способа вызывает некоторые проблемы, потому такой способ крайне не рекомендуется... взамен этому есть адекватная функция preg_replace_callback(...)..

 

 

символ ^ в начале паттерна указывает, что поиск совпадений следует вести от начала исходной строки, а символ $ в конце паттерна указывает, что конец поиска совпадений должен совпадать с концом исходной строки.. в нашем случае мы указали, что наш паттерн должен полностью соответствовать исходной строке..

Например, паттерн  /^\d+/   для строки  123абв456  найдет совпадение  123,

а паттерн  /\d+$/  для той же строки найдет совпадение  456.. надеюсь суть ясна, да?..

 

 

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

 

Внутренние модификаторы..

Например,  /((?i)abc)def/  найдет совпадение со строкой Abcdef, но не со строкой  AbcDef.. внутренний модификатор действует до конца ближайшего субпаттерна..

 

 

Альтернативные субпаттерны..

Например,  /(abc|def)/  найдет совпадения в строках  abc  и def..

 

 

Незахватывающие субпаттерны..

Например,  /(\w+)(?:\d+)/  найдет совпадение в строке  abcd123, но в массиве совпадений будет лишь один элемент abcd, второй субпаттерн не будет сохранен..

 

Незахватывающие субпаттерны можно совмещать с внутренними модификаторами,

например, /(?i:abc)def/  будет эквивалентно  /(?:(?i)abc)def/

p.s.: использование внутренних модификаторов не совсем оправдано, кроме как худшей читаемости кода они ничего не дают.. но это лишь мое имхо..

 

 

Ссылки на субпаттерны..

Например, /(m[ao])\\1/  найдет совпадение в строках  mama, momo,  но не в строках mamo или moma.. при выполнении паттерна значение первого субпаттерна, заключенного в скобки, сохраняется в буфер, и в дальнейшем оно может быть использовано для поиска соответствия..

 

 

Утверждения, обратные утверждения..

Например, /ma(?=[nm])/  найдет совпадение в строках man и mam.. вы спросите, а в чем отличие от паттерна вида /ma[nm]/ .. отличие будет в том, что в первом случае обработке подвергается лишь ma, а во втором случае все слово man, mam.. другими словами, утверждения не участвуют в разборе паттерна.. надеюсь, что кто-то понял.. :-)

 

Есть также отрицательные утверждения, например, /ma(?!m)/ найдет совпадения в строках mah, mag, mak и т.д., но не в строке mam..

 

Если утверждение нуно поставить перед искомым паттерном, то синтаксис немного другой:

Например, /(?<=[jm])am/  найдет совпадение в строках jam и mam..

Например, /(?<!m)am/  найдет совпадение в строках ham, jam, lam и т.д., но не в строке mam..

 

 

Условные субпаттерны..

В общем виде условные субпаттерны можно записать как:

(? (условие) субпаттерн1 | субпаттерн0 )   или вкратце  (? (условие) субпаттерн1 )

при выполнении условия  выполняется поиск соответствий по субпаттерну1, если условие не выполняется то идет поиск по субпаттерну0..

Например, есть паттерн  /(\d+)([\s\.\-]+)(?(?=\d)(\d+)|(\w+))\\2(\d+)/ ... кстати как думаете, что делает этот паттерн?.. есть предположения?.. а паттерн этот разбирает строку даты.. найдет совпадение в строках 23.12.12, 23-12-2012, 23 Dec 2012, но не в строках 23 12-12..

надо отметить, что используя условный субпаттерн мы разделяем сохраняемые субпаттерны, например, 23-12-2012 вернет массив элементов:

Array(
   [0] => 23-12-2012
   [1] => 23
   [2] => -
   [3] => 12
   [4] =>
   [5] => 2012
)

тогда как 23 Dec 2012 вернет:

Array(
   [0] => 23 Dec 2012
   [1] => 23
   [2] =>
   [3] =>
   [4] => Dec
   [5] => 2012
)

 

 

На этом собственно заканчивается история о регулярных выражениях.. есть правда еще однократные и рекурсивные субпаттерны, но в силу малой применимости рассматривать их мы не будем..

 

Посмотреть жизненные примеры использования регулярных выражений можно в этой статье..

Комментариев к статье нет..
[ Добавить ] комментарий
Поля с пометкой * обязательны для заполнения

*Ваше имя
  Ваш сайт  
  Ваш город
*Ваше сообщение

Код подтверждения
*Код с картинки   @
код на картинке содержит только цифры (0..9) и буквы англ. алфавита (A..Z)