Анимация
JavaScript


Главная  Библионтека 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 [ 98 ] 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189

( Замечание

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

Опять же, сформулируем словами то, что нам нужно: "Часть слова после последнего прямого или обратного слэша или, в крайнем случае, после начала строки, присвой переменной $fileName, а "начало строки" - переменной $dirName". Формулировку "часть слова после последнего слэша" можно заменить на несколько другую: "Часть слова, перед которой стоит слэш, но в нем самом слэша нет".

Выводы

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

строке $inFile все, что после последней точки (и ее саму), или, в крайнем случае, "конец строки" на строку .out, и присвой это переменной $outFile".

Пример второй

Давайте теперь рассмотрим другой пример. Нам нужно разбить полное имя файла на две составляющие: каталог, в котором расположен файл, и само имя файла. Как мы знаем, для этого в PHP встроены функции basename() и dirname(), рассмотренные выше. Но предположим для тренировки, что их нет. Вот как мы реализуем требуемые действия:

$slash1=strrpos($fullPath,/);

$slash2=strrpos($fullPath,\\);

$slash=max($slash1,$slash2);

$dirName=substr($fullPath,0,$slash);

$fileName=substr($fullPath,$slash+1,10000);

Здесь мы воспользовались тем фактом, что strrpos() возвращает false, которое интерпретируется как 0, если искомый символ не найден. Обратите внимание на то, что пришлось два раза вызывать strrpos() , потому что мы не знаем, какой слэш будет получен от пользователя - прямой или обратный. Видите - код все увеличивается. И уменьшить его почти невозможно.



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

Терминология

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

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

Итак, мы имеем выражение и мы имеем строку. Операцию проверки, удовлетворяет ли строка этому выражению (или выражение - строке, как хотите) условимся называть сопоставлением строки и вхражения. Если какая-то часть строки успешно сопоставилась с вхражением, мы назовем это совпадением. Например, совпадением от сопоставления вхражения "группа букв, окруженная пробелами" к строке "ab cde fgh" будет строка "cde" (ведь только она удовлетворяет нашему вхражению). Возможно, дальше мы с этим совпадением захотим что-то проделать - например, заменить его на какую-то строку или, скажем, заключить в кавычки. Это - типичный пример сопоставления с заменой. Все эти возможности реализуются в PHP в виде функций, которые мы сейчас и рассмотрим.

Использование регулярных выражений в PHP

Вернемся на минуту опять к практике. Любое регулярное вхражение в PHP - это просто строка, его содержащая, поэтому функции, работающие с регулярными выражениями, принимают их в параметрах в виде обычных строк.

Сопоставление

bool ereg(string $expr, string $str [,list &$Matches])

Функция пытается сопоставить выражение $expr строке $str и в случае удачи возвращает true, иначе - false. Если совпадение было найдено, то в список $Matches (конечно, если он задан) записываются отдельные участки совпадения (как выделять эти участки на языке RegEx, мы рассмотрим немного позже). Пока скажу только, что в $Matches[0] всегда будет возвращаться подстрока совпадения целиком.



Примечание

В четвертой версии интерпретатора поддерживается также и стандарт PCRE (Perl-Compatible Regular Expression - Регулярные выражения языка Perl). Его выражения несколько более универсальны. Прочитать о формате PCRE можно в любой книге по Perl.

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

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

□ простые символы, а также управляющие символы, играющие роль их "заменителей";

□ управляющие конструкции (квантификаторы повторений, оператор альтернативы, группирующие скобки и т. д.);

□ так называемые мнимые символы (в строке их нет, но, тем не менее, они как бы помечают какую-то часть строки - например, ее конец).

Сопоставление с заменой

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

string ereg replace(string $expr, strint $str, string $strToChange)

Эта функция занимается тем, что ищет в строке $str все подстроки, соответствующие вхражению $expr, и заменяет их на $strToChange. В строке $strToChange могут содержаться некоторые управляющие символы, позволяющие обеспечить дополнительные возможности при замене. Их мы рассмотрим позже, а сейчас скажу только, что сочетание \0 (в PHP эта строка будет записываться как "\\0" ) будет заменено на найденное совпадение целиком.

Язык RegEx

Существует несколько разновидностей языков, используемых для записи регулярных выражений и работы с ними. У всех них есть много общего, но отдельные части все же отличаются. В PHP версии 3 стандартно реализован только один из языков - он называется RegEx.



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 [ 98 ] 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189