Отправляет email-рассылки с помощью сервиса Sendsay

Программирование в Web

  Все выпуски  

Программирование в Web Выпуск 23 от 21/04/2007 Основы PHP - Урок-16


 
Программирование в web

ОСНОВЫ PHP
 

 
Внимание!!!
Все материалы уроков, публикуемых в этом и во всех последующих выпусках рассылки «Программирование в web», являются интеллектуальной собственностью авторов и ведущих рассылки. По всем вопросам размещения или публикации данных материалов на собственных ресурсах или где-либо еще, или иного использования, не связанного с личным ознакомлением и самостоятельным обучением, - обращайтесь на адрес автора. Любое использование этих материалов в коммерческих или иных целях, явно не разрешенное автором, является незаконным.
 

 
У Р О К    16
Здравствуйте уважаемые подписчики!

Ну вот, выдалось чуть времени и я наконец-то смог сделать очередной выпуск. В этом выпуске продолжим изучение регулярных выражений. В нем мы изучим основные элементы языка PCRE, ну и, возможно, затронем немного POSIX. Функции PHP для работы с регулярными выражениями будем изучать в следующих уроках, а заодно и рассмотрим несколько примеров их применения. Итак начинаю…



РЕГУЛЯРНЫЕ ВЫРАЖЕНИЯ в PHP (ЧАСТЬ-II):


Простые символы:

Большинство буквенно-цифровых символов в регулярном выражении чаще всего означают сами себя, но есть и специальные простые символы, означающие некие последовательности:


«\s» — соответствует пробельному символу;
«\t» — знаку табуляции;
«\n» — перевод строки;
«\r» — возврат каретки;
«\r» и «\n» часто используются в паре, вот таким образом —«\r\n». Здесь надо заметить, что все эти последовательности в регулярном выражении обозначают именно цельный единый символ.
«\S» — любой символ кроме пробельного;
«\w» — любая буква или цифра;
«\W» — не буква и не цифра;
«\d» — цифра от 0 до 9;
«\D» — все, что угодно, но только не цифра.

У этих простых символов имеется и альтернативная запись:

«[:alpha:]» — любая буква;
«[:digit:]» — любая цифра;
«[:alnum:]» — любая буква или любая цифра;
«[:space:]» — любой пробельный символ;
«[:blank:]» — любой пробельный символ или символы с кодами 0 и 255;
«[:cnrtl:]» — любой управляющий символ;
«[:graph:]» — любой символ псевдографики;
«[:lower:]» — любая буква в нижнем регистре;
«[:upper:]» — любая буква в верхнем регистре;
«[:print:]» — любой печатаемый символ;
«[:punkt:]» — любой знак пунктуации;
«[:xdigit:]» — любая цифра или буква от A до F.

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


«^» — соответствует позиции курсора в самом начале строки. Обратите внимание, не первому символу в строке, а именно позиции до самого первого символа в строке. Так этот символ работает в однострочном режиме, а в многострочном он обозначает начало каждой новой подстроки, то есть тоже позицию до самого первого символа в подстроке. Данное действие у этого символа только если он употреблен в самом начале регулярного выражения;
«$» — соответствует позиции в самом конце строки, то есть именно позиции после самого последнего символа в строке перед «\n» Этот символ действует так, только если употреблен в самом конце регулярного выражения.
Именно такой вариант применения мы уже рассмотрели в нашем примере шаблона адреса электронной почты из каркаса гостевой книги.
«\b» — соответствует началу или концу слова. То есть любая позиция между «\w\W» и «\W\w» заставит сработать наше выражение;
«\B» — любая позиция, но только не начало и не конец слова;
«.» — в многострочном режиме совпадает с любым символом, кроме «\n», а в однострочном режиме вообще с любым символом;
«\A» — мнимый символ, совпадающий с началом данных, то есть с позицией перед первым символом строковой переменной. Используется в многострочном режиме, а в однострочном вместо него используется «^»;
«\z» — мнимый символ, совпадающий с концом данных, с позицией после последнего символа строковой переменной.


Квантификаторы повторения:

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


«+» — «плюс» — буквально указывает, что стоящее перед ним регулярное выражение должно повториться один или несколько раз, то есть, не менее одного раза;
«*» — «звездочка» — стоящее перед ним регулярное выражение должно повториться ноль или более раз. У этого квантификатора есть так называемая «жадность». Это значит, что будет найдено несколько совпадений, то квантификатор выберет наиболее длинное, а те, которые короче, просто проигнорирует;
«?» — «знак вопроса» ноль или одно совпадение. Данный квантификатор «нежадный», более того, он способен несколько умерить «жадность» других квантификаторов, если будет употреблен вместе с ними;
«{n,m}» — сработает, если шаблон совпадет не менее n и не более m раз;
«{n}» — сработает, если будет найдено точно n свопадений;
«{n,}» — n или более совпадений;
А вот эквиваленты «+», «*» и «?»:
«{1,}» — наш «нежадный» плюс;
«{0,}» — «нежадная» звездочка;
«{0,1}» — эквивалентен знаку вопроса.
В противовес «жадным» квантификаторам можно задать «ленивые» квантификаторы. Делается это с помощью символа «?» вот таким образом: «+?», «*?», «{}?», «??». Эти квантификаторы не будут искать самые длинные совпадения, а сработают на первое же попавшееся, таким образом будет учтено почти любое совпадение.

Отрицательные классы:

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


«[^xnm]» — буквально означает, что нужно искать любой символ, кроме прямо указанных внутри квадратных скобок сразу после символа «^». Прошу снова обратить внимание, что такое действие символа «^» только внутри квадратных скобок, а вне их и в самом начале регулярного выражения этот символ означает позицию перед самым первым символом в строке совпадения.
Вот такой шаблон «/<[^>]+>/» сработает на все HTML-теги в строке.

Модификаторы:

Символы, которые используются вне самих шаблонов, сразу после последнего ограничителя регулярного выражения, но которые устанавливают различные режимы обработки шаблонов функциями PHP:


«i» — игнорирование регистра символов при поиске совпадений;
«x» — пропуск пробелов и комментариев. Этот модификатор удобно применять, если вы желаете сделать ваш шаблон более удобочитаемым, разбив каждый блок выражения по разным строкам;
«m» — многострочность - означает, что поиск будет вестись в многострочном режиме, по всем строкам;
«s» — однострочный режим - строка, в которой будет производиться поиск будет единственной, во всех остальных строках в выражении поиск производиться не будет;
«e» — при замене по регулярному выражению выполнит php-программу, то есть он работает только в функции preg_replace(), при этом трактуя второй параметр (на что заменять) как код программы на php, результат работы которой и будет заменять искомое. Данный модификатор несколько несовершенен, поэтому использовать его надо с осторожностью. В некоторых случаях его применение может вызвать ошибку.

Группирующие скобки:

Если ваше регулярное выражение (шаблон для поиска), состоит из нескольких частей, его лучше всего сгруппировать, то есть каждую часть целого выражения (подвыражение) можно и даже нужно заключить в парные круглые скобки. Таким образом мы поступали в примере с проверкой корректности введенного email-адреса:


Фактически выражение —
«/^([a-zA-Z0-9_.-]+)@([a-zA-Z0-9_.-]+)([.]{1})([a-zA-Z0-9]{2,4})$/is»
состоит из нескольких подвыражений:
«([a-zA-Z0-9_.-]+)»;
«@»;
«([a-zA-Z0-9_.-]+)»;
«([.]{1})»;
«([a-zA-Z0-9]{2,4})»

Как видите, каждое такое подвыражение является полноценным выражением, но замкнутым в группирующие скобки. Это очень удобно, если нам необходимо задать сложный шаблон для поиска совпадений. Группирующие скобки можно использовать любые, и квадратные и фигурные и просто круглые.



Незахватывающий поиск:

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



Позитивный просмотр вперед:

«(?=подвыражение)» — подвыражение может быть любым полноценным регулярным выражением – когда в выражении встречается такая конструкция, текущая позиция считается допустимой, если с нее начинается подстрока, совпадающая с подвыражением в скобках. При этом захвата символов не происходит, и следующая конструкция будет работать с той же самой позицией в строке, с которой работала первая конструкция



Негативный просмотр вперед:

«(?!подвыражение)» — практически тоже самое, что и первая конструкция, только с отрицанием, то есть не совпадает с подвыражением



Позитивный просмотр назад:

«(?<=подвыражение)» — осуществляет просмотр не в прямом, а в обратном направлении



Негативный просмотр назад:

«(?<!подвыражение)» — просмотр назад с отрицанием, то есть не совпадает с подвыражением



Обратные слэши («\»):

Эти символы достаточно сложны в регулярных выражениях. Выражения с их использованием трудно читать и писать. Но частенько без них не обойтись. Допустим в регулярном выражении встречается какой-либо спецсимвол, который должен в шаблоне поиска означать сам себя (ну, для примера, знак «$»). Значит нам надо обязательно его предварить обратным слэшем, чтобы отключить его специальное действие. Но это в регулярных выражениях PCRE. В свою очеред, эти регулярные выражения используются в PHP, для которого действуют те же правила, то есть спецсимвол должен быть либо удвоен, либо предварен обратным слэшем. И таким образом законченное выражение с использованием специального символа будет содержать уже не один обратный слэш, а целых два. Такое поведение обратного слэша называют эффектом (или синдромом) зубочистки.

Разберем пример, который приводит Дмитрий Котеров в своей книге (не стал я долго придумывать и изобретать и решил взять именно его пример, так как он довольно удачно иллюстрирует тот самый эффект зубочистки). Допустим нам надо найти некое имя файла в строке, предваренное обратным слэшем (как в ОС Windows). Такое регулярное выражение будет выглядеть так:

$regexp='/\\\\filename/';

Заметили? Единственный слэш, который мы искали вдруг превратился в целых четыре. Как же это произошло?

Удвоенный слэш в строках PHP - это один символ слэша при выводе. Но в PCRE, все тоже самое, удвоенный слэш - это один символ слэша на выходе. Таким образом происходит следующее: PCRE ищет совпадения и на выходе отдает в PHP \\filename, PHP же получив на вход \\filename на выход отдаст уже \filename. Теперь примерчик посложнее:

Ищем любое имя каталога, после которого идет любое имя файла (разбираем путь к файлу). Выражение (шаблон) для такого поиска будет выглядеть так:


$regexp='/\\S+\\\\\\S+/';

Уже целых шесть обратных слэшей. Чтобы увидеть, как будет получать на вход PHP найденное совпадение, нужно шаблон поместить в переменную и просмотреть ее в браузере по команде echo или print. Так мы сможем увидеть, глазами PCRE и PHP наше регулярное выражение. А заодно и подправить, если возникнет необходимость.


В качестве примера, в дополнение к тому, который позволяет проверить корректность email-адреса приведу еще парочку:


«'/(\S+)@([a-z0-9.]+)/is'» — как думаете, чему может соответствовать это регулярное выражение? Оно почти эквивалентно предыдущему примеру проверки email-адреса. Буквально, в качестве имени ящика (до «@») может идти один или более любых непробельных символов – это первое подвыражение. Второе подвыражение - проверяет доменные имена, ну а модификаторы i и s – говорят нам, что при поиске регистр символов учитывать не надо и поиск производится в однострочном режиме. На самом деле это регулярное выражение лучше всего применять для поиска и выцарапывания из какого-то текста email-адресов, но не для проверки корректности вводимого адреса. Ведь согласитесь, что, например адрес m@mail.r - этим шаблоном тоже будет воспринято нормально, а вот существует ли домен первого уровня, состоящий всего лишь из одного символа? Думаю, что таких нет, во всяком случае я не встречал. А многие ли бесплатные сервера позволяют создавать почтовые ящики с именами в которых содержится, например, знак хэш («#»)? Тоже не многие. В общем, это выражение годится для поиска адресов, а для проверки их корректности лучше использовать тот шаблон, который мы использовали в нашей гостевой книге.

И еще один пример:


«'|^\s*((\d+)\s*[[:punkt:]]\s*(\d+)\s*[[:punkt:]]\s*(\d+))\s*$|xs'».

Чему же может соответствовать этот шаблон? Он довольно прост, я думаю, вам самим не составит труда разобраться, чему он может соответствовать. Но, на всякий случай, я поясню. Этот шаблон больше всего похож на дату в произвольной записи. То есть три группы цифр разделенных между собой любым знаком пунктуации или любым пробельным символом или и тем и другим сразу. Вместо плюсов было бы конечно лучше использовать квантификаторы повторений в фигурных скобках, например для первой и второй группы этот квантификатор будет таким — {1,2} — один или два цифровых символа, а для третьей группы — {2,4}. На самом деле этот шаблон можно было бы написать и несколько проще и при этом предусмотреть большие точности, а также можно было бы написать так, чтобы можно было бы проверить корректность записи даты. Но это я предлагаю сделать вам самостоятельно. Ваши варианты различных шаблонов можете нап равить мне для опубликования в следующих выпусках, с пометкой «урок-16». Заодно попробуем вместе поработать над ошибками и попрактиковаться. Предложите свои варианты проверки корректности email-адресов или поиска адресов. Попробуйте написать регулярное выражение для поиска web-адресов с префиксом http:// или без него (такое регулярное выражение очень может пригодиться при написании гостевых книг, форумов и так далее, когда мы желаем дать посетителю возможность опубликовать какой-либо адрес в виде действующей ссылки). Не стесняйтесь. Предлагайте. Пишите.


Ну что же, на этом данный урок заканчиваю. В следующих уроках будем изучать функции для работы с регулярными выражениями. Ведь надо же нам как-то будет применять полученные знания. Вообще, хотелось бы заметить, не стоит считать работу с регулярными выражениями слишком сложной и ненужной. Это не совсем так. То, что сначала построение шаблонов покажется сложным - это действительно так, но при достаточном упорстве вы сможете освоить их достаточно быстро. О ненужности, ну что тут сказать, конечно, можно построить какой-то проект совсем не прибегая к использованию регулярных выражений, но их применение, сильно облегчит вам задачу в сложных местах ваших проектов, сможет помочь вам сделать ваши разработки более мощными и гибкими, сделать их более интеллектуальными. Так что не пренебрегайте этой темой. Еще лучше, если вы не станете ограничиваться в изучении регулярных выражений только лишь выпусками рассылки, а воспол ьзуетесь многочисленной литературой по данной теме.


До следующего выпуска.


 

 
Объявления!!!

Если у вас возникли какие-то вопросы, не стесняйтесь, задавайте. Для этого, всего лишь, пошлите на мой адрес письмо с вопросом и с темой, в которой обязательно укажите какого урока и какого языка касается вопрос. Например, тема может быть такой - «Основы PHP. Урок 10. Вопрос». Также, с такой же темой и на этот же адрес вы можете прислать и свои дополнения к уроку. Если дополнения будут существенными, то в последующих уроках они обязательно будут учтены.

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

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

Маленькая просьба. Многие из вас присылают мне запросы на отправку им того или иного, не полученного ранее, выпуска рассылки. У меня не всегда есть возможность это сделать. Поэтому предлагаю вам для начала посмотреть нужный выпуск в архиве рассылки. Рассылка выходит сразу на трех рассыльных сервисах, и по некоторым причинам (мне не известным) некоторые сервисы не принимают адресов, в которых встречаются именя конкурирующих рассыльных сервисов, по этой причине я опубликую только одну ссылку на архив рассылки только одного рассыльного сервиса, а именно Content.mail.ru. Вот ссылка на на этот архив рассылки - http://content.mail.ru/pages/p_21931.html. В обще м-то это объявление наверное лишнее, ведь в каждом выпуске каждой рассылки, вне зависимости от того, на каком сервисе она выходит, всегда указан этот самый адрес архива рассылки. На сабскрайб.ру и на контент.мэйл.ру этот адрес указывается в самом низу выпуска, а на мэйллист.ру - в самом верху выпуска. Так что, при достаточном внимании, вы сами легко сможете найти нужную ссылку на архив рассылки.

 

 
Немного смеха не помешает:

******

– Срубил Добрыня голову Змею Горынычу, а у того вместо одной две выросло. Срубил Добрыня эти две головы, а вместо них выросло уже четыре. Добрыне стало интересно и он, еще на протяжении двух часов, издевался над бедной зверюшкой, пока та не стала похожа на веник.


******

– В каждой крупинке - сила Великого Джедая! Соль йодированная.


******

– Все рефераты, курсовые и дипломы пишутся студентами по распространенной системе «Копипаста», давно разработанной широко известным ученым Контроловым С.В.


******

Директор зоопарка жалуется другу:
 – Слон совсем голодный, а денег нет.
 – Да ты посмотри, сколько вокруг палаток с фруктами.
 – А кто мне без денег даст?
 – А зачем тебе, ты слона выпусти, и пусть ему попробуют не дать!


******

– А ларчик просто ломом открывался...


******

– В Чернобыле вырастили самый большой в мире огурец и повезли его на международную выставку в Париже. По дороге огурец всех съел.


******

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


******

– Иван-царевич опустил лук и закончилась сказка о Чипполино.


******

– В современном автомобиле все продуманно до мелочей. Уснул за рулем, бах, и твое лицо уже на подушке.


******

– В советские времена обезьян в питомнике учили разбирать и собирать автомат. Эксперимент был свернут, когда примат открыл огонь на поражение, получив несвежий банан.


******

– Дед Мазай по весне запасался зайчатиной на целый год.


******

– Единственная светлая полоса в жизни - это рулон туалетной бумаги.


******

– Ой! – вскрикнул утром крокодил Гена, отрыгивая комок бурой шерсти...


******

– Тяжело дыша перегаром, мимо прошла стайка первоклассниц.


******

– Из-за неосторожности крановщику понадобилось всего три секунды чтобы спуститься с крана.


******

– Милицейская сводка: «Два автомобиля КамАЗ, груженные автомобилями ВАЗ, были угнаны вчера с платформы автомобиля БелАЗ».


******

 

 
Внимание!!!
Все материалы уроков, публикуемых в этом и во всех последующих выпусках рассылки «Программирование в web», являются интеллектуальной собственностью авторов и ведущих рассылки. По всем вопросам размещения или публикации данных материалов на собственных ресурсах или где-либо еще, или иного использования, не связанного с личным ознакомлением и самостоятельным обучением, - обращайтесь на адрес автора. Любое использование этих материалов в коммерческих или иных целях, явно не разрешенное автором, является незаконным.
 

 
Наш проект и наши друзья
Автор рассылки — Anatolick
Архив рассылки — http://content.mail.ru/pages/p_21931.html
Сайт проекта — «Russian discussions Zone»
Движок для сайтов — «Tanat-Engine»
Проект Web Help — «Web-Help.int.ru»
Дискуссионный лист — «Все для Всех о РС»
Дискуссионный лист — «File Info Masters»
Дискуссионный лист — «Напряги мозги»
Дискуссионный лист — «Ищем все…»
Дискуссионный лист — «Все обо Всем по Email»
Дискуссионный лист — «Внимание! Розыск…»
Дискуссионный лист — «Английский для Всех и каждого»
Группа стандартизации в Web — W3C.org
 

В избранное