Анимация
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

( Замечание

Пожалуйста, обратите опять внимание на то, что слэши должны удваиваться.

Нетрудно догадаться, как "оно" работает: просто во время замены везде вместо сочетания \1 подставляется содержимое кармана номер 1.

Исходя из этого, имеем следующую программу на PHP, выполняющую требуемые действия:

$str=" 15-16-2000 "; к примеру

Разбиваем строку на куски при помощи ereg

ereg("- *(([0-9]+)-([0-9]+)-([0-9]+)) *$",$str,$Pockets);

Теперь разбираемся с карманами

echo "Дата без пробелов: $Pockets[1] <br>"

echo "День: $Pockets[2] <br>";

echo "Месяц: $Pockets[3] <br>";

echo "Год: $Pockets[4] <br>";

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

- *([0-9]+) *[-./] *([0-9]+) *[-./] *([0-9]+) *$

Использование карманов в функции замены

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

Предположим, нам нужно все слова в строке, начинающиеся с "доллара" $ , сделать "жирными", - обрамить тэгами <b> и </b>, - для последующего вывода в браузер. Это может понадобиться, если мы хотим текст некоторой программы на PHP вывести так, чтобы в нем выделялись имена переменных. Очевидно, выражение для обнаружения имени переменной в строке будет таким: \$[a-zA-z ][[:alnum:]]*.

Но как нам использовать его в функции ereg Replace() ? Вот фрагмент программы, которая делает это:

$str="<? $a=10; for($i=0; $i<10; $i++) echo $i; ?> к примеру

$str=ereg Replace("(\\$[a-zA-Z ][[:alnum:]]*)","<b>\\1</b>",$str);



( Замечание

Хотя регистр и не учитывается при поиске, в карманах $Matches все найденные подстроки все же запишутся с точным сохранением регистра букв.

string eregi replace(string $expr, strint $str, string $strToChange) То же, что и ereg replace() , но без учета регистра буквенных символов.

Использование карманов в функции сопоставления

И даже на том, что было описано выше, возможности карманов не исчерпываются. Мы можем задействовать содержимое карманов и в функции ereg() - раньше, чем закончится сопоставление. А именно, управлять ходом поиска на основе данных в карманах.

В качестве примера рассмотрим такую далеко не праздную задачу. Известно, что в строке есть подстрока, обрамленная какими-то HTML-тэгами (например, <b> или <pre>), но неизвестно, какими. Требуется поместить эту подстроку в карман, чтобы в дальнейшем с ней работать. Разумеется, закрывающий тэг должен соответствовать открывающему - например, к тэгу <b> парный - </b>, а к <pre> - </pre>.

Задача решается с помощью такого регулярного выражения:

<([[:alnum:]]+)>([-<]*)</\1>

При этом результат окажется во втором кармане, а имя тэга - в первом. Вот как это работает: PHP пытается найти открывающий тэг, и, как только находит, записывает его имя в первый карман (так как это имя обрамлено в выражении первой парой скобок). Дальше он смотрит вперед и, как только наталкивается на </, определяет, следует ли за ним то самое имя тэга, которое у него лежит в первом кармане. Это действие заставляет его предпринять конструкция \1 , которая замещается на содержимое первого кармана каждый раз, когда до нее доходит очередь. Если имя не совпадает, то такой вариант PHP отбрасывает и "идет" дальше, а иначе сигнализирует о совпадении.

Вот фрагмент программы, который все описанное делает тремя строчками:

$str = "Hello, this <b>word</b> is bold!"; if(ereg("<([[:alnum:]]+)>([-<]*)</\\1>",$str,$Pockets))

echo "Слово $Pockets[2] обрамлено тэгом <$Pockets[1]>";

Дополнительные функции

bool eregi(string $expr, string $str [,list &$Matches]) То же, что и ereg() , только без учета регистра символов.



Перед слэш почему-то не ставится. Будьте особо внимательны!

list split(string $pattern, string $string [,int $limit])

Эта функция очень похожа на explode(). Она тоже разбивает строку $string на части, но делает это, руководствуясь регулярным выражением $pattern. А именно, те участки строки, которые совпадают с этим выражением, и будут служить разделителями. Параметр $limit, если он задан, имеет то же самое значение, что и в функции explode() - а именно, возвращается список из не более чем $limit элементов, последний из которых содержит участок строки от ($limit-1)-го совпадения до конца строки.

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

list spliti(string $pattern, string $string [,int $limit])

Аналог функции split() , который делает то же самое, только при сопоставлении с регулярным выражением не учитывается регистр символов.

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

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

Имя и расширение файла

Задача: для имени файла в $fname установить расширение out независимо от его предыдущего расширения.

int quotemeta(string $str)

Часто бывает нужно гарантировать, чтобы в какой-то переменной-строке ни один символ не мог трактоваться как метасимвол. Этого можно добиться, предварив каждый из них наклонной чертой, что и делает функция quotemeta(). А именно, она "заслэшивает" следующие символы: . , \\, +, *, ? , [ - ] , ( $ ).



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