[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Регулярные выражения для самых маленьких
Страницы: 1, 2
welder
Регулярные выражения для самых маленьких

Регулярные выражения — это очень мощное средство для обработки ваших данных.

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

Давайте для начала разберем простенький шаблон который ищет содержимое заголовков "#<(h1|h2|h3)>(.*)</\\1>#Uis"

Изображение


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

Основы

1. Ограничитель шаблона

В нашем случае символ "#" - является ограничителем шаблона им может служить любой не алфавитно-цифровой символ, кроме обратного слеша "\". Очень часто в качестве ограничителя используется "/","|","%","$" или как в моём случае "#". Если в шаблоне нужно использовать символ который у нас выбран в качестве ограничителя перед ним добавляется обратный слеш "\" (пример: "#<b>\#</b>#i")

2. Шаблон

Шаблон это то что находится между ограничителей у нас это "<(h1|h2|h3)>(.*)</\\1>"
в нашем шаблоне так же имеются под-шаблоны: "(h1|h2|h3)" который ищет совпадение с h1 или h2 или h3, и "(.*)" который ищет совпадение между заголовков
и также у нас есть обратная ссылка \\1 о которой будет рассказано в пункте 4

Давай рассмотрим синтаксис шаблонов, именно в нём и состоит вся мощь регулярных выражений:

| - Означает логическое или.
#а|о#
такой шаблон ищет "a", если не найдет, будет искать "о".
совпадет - "любитель пива" (нашлось 'а')
совпадет - "люблю пиво" (нашлось 'о')
не совпадет - "пиву нет!!"


ˆ - этот знак в шаблоне обозначает, чтобы в начале обязательно стояли следующие за ним символы.

#ˆп#

такой шаблон ищет "п" и найдет, если он стоит первым:
не совпадет - "водка непутинка" (нет 'п' в начале)
совпадет - "путинка водка" ('п' в начале)

$ - этот знак в шаблоне обозначает , чтобы в конце обязательно стояли, предшествующие ему символы.

#т$#

такой шаблон ищет "т" и найдет, если он стоит последним:
не совпадет - "водка плохо" (нет 'т' в конце, нельзя)
совпадет - "пива нет" ('т' в конце)

. - точка в шаблоне обозначает, что шаблон совпадет с любым символ строки, кроме [\n].

#.#

то есть, этот шаблон совпадет с любыми символами, кроме знака [\n]:
совпадет - "абв" (выведет только 'а' 'б' 'в')
совпадет - "а\nб\nв" (выведет только 'а' 'б' 'в', [\n] не выведет)


* - этот знак в шаблоне обозначает количество совпадений, это числитель ноль или более раз


#а*#

такой шаблон ищет "а" и найдет только в том случае, если "а" будет находиться в строке ноль или более раз. То есть, совпадет с любой строкой и вернет ее:
совпадет - "пива нет" (есть 'а')
совпадет - "спирт хорошо" (нет 'а', но все - равно совпадает)

+ - этот знак в шаблоне обозначает количество совпадений, это числитель 1 или более раз

#п+#

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

? - этот знак в шаблоне обозначает количество совпадений, это числитель 0 или 1 раз

#п?#

такой шаблон ищет "п" и найдет только в том случае, если "п" будет находиться 0 или 1 раз. То есть, если "п" не будет больше одной:
не совпадет - "пиво пьют" (есть 'п', но больше 1 раза)
совпадет - "пива нет" (есть 'п' один раз)
совпадет - "водка есть" (нет 'п', но все - равно совпадет)

{ } - эти знаки в шаблоне обозначают сколько раз должно быть совпадение

? тоже самое, что и {0,1} - ноль или один раз
* тоже самое, что и {0, } - ноль или более раз
+ тоже самое, что и {1, } - один или более раз
То есть, {2,3} - должно быть два или три совпадения. Ставится после символа, который будем искать без пробелов и через запятую: {1,9} {0,35}, итд. Первая цифра обозначает минимум совпадений, последняя - максимум.

#пиво{2,3}# - 'пиво' должно быть два или три раза
#водка{1,2}#- 'водка' должно быть один или два раза


\ - обратный слеш в шаблоне обозначает подстановку.
#\.# - мы предварили точку обратным слешем и, теперь, наш шаблон будет искать точку, и совпадет только с ней в нашем тексте, а не со всеми символами, как было в последнем примере. То есть, обратный слеш служит для обозначения самих метасимволов, как обычных символов текста. Так же, все метасимволы надо предварять слешем для обозначения самих себя.

Подстановка метасимвола:
\\ \. \| \( \) \[ \] \{ \} \? \* \+ \ˆ \/ \# \!
Подстановка класса символов
\d - любой цифровой символ [0-9]
\D - любой НЕ цифровой символ [Ր-9]
\s - любой пробельный символ [\t\ \r\f\n]
\S - любой НЕ пробельный символ [ˆ\t\ \r\f\n]
\w - любой алфавитно-цифровой символ [a-zA-Z0-9_]
\W - любой НЕ алфавитно-цифровой символ [ˆa-zA-Z0-9]

Кроме этого, классы символов можно обозначать так:
[[:alnum:]] - все алфавитно-цифровые символы [a-zA-Z0-9]
[[:alpha:]] - все алфавитные символы [a-zA-Z]
[[:blank:]] - символ табуляции и пробел [\t ]
[[:cntrl:]] - все управляющие символы
[[:digit:]] - все десятичные цифры [0-9]
[[:graph:]] - все печатные символы, за исключением пробела
[[:lower:]] - все строчные буквы [a-z]
[[:upper:]] - все прописные буквы [A-Z]
[[:print:]] - все печатные символы
[[:punct:]] - все знаки препинания [\.,;:-]
[[:space:]] - все пустые символы
[[:xdigit:]] - все шестнадцатиричные цифры

Если вы поставите [ˆ[:alnum:]] - любой НЕ алфавитно-цифровой символ, то есть это полная противоположность [[:alnum:]]. То есть, любой класс вы можете инвертировать посредством 'ˆ'.

Подстановка претензий
\b - на границе слова
\B - не на границе слова
\A - в начале строки
\Z - в конце строки
\z - в конце текста

3. Подшаблон

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

в нашем шаблоне два подшаблона: "(h1|h2|h3)" который ищет совпадение с h1 или h2 или h3, и "(.*)" который ищет совпадение между заголовков


4. Обратная ссылка

Это ссылка на подшаблон в нашем случае //1 мы обращаемся к первому подшаблону в самом шаблоне.То есть выражение "#<(h1|h2|h3)>(.*)</\\1>#Ui" равно "#<(h1|h2|h3)>(.*)</(h1|h2|h3)>#Ui"

5. Модификаторы
Функционирование регулярных выражений можно видоизменить используя модификаторы их значение и использование описано ниже.

i - игнорировать регистр
#шаблон#i
будет искать шаблон, игнорируя регистр в тексте поиска.

s - метасимвол '.' соответствует и символу [\n], то есть классу [\0-\xFF]
#шаблон#s
будет искать шаблон, где '.' Игнорирует видит [\n], то есть метасимвол точка будет так же возвращать и перевод каретки на новую строку.

U - минимизировать числитель, то есть искать как можно меньше совпадений
#шаблон#U
будет искать шаблон, с как можно меньшим совпадением раз. Если мы ставили в шаблоне #a?# - действие этого модификатора примерно такое же, как и минимизатора '?' в самом шаблоне.

m - претензии 'ˆ' и '$' учитывают [\n]
#шаблон#m
если в шаблоне будут метасимволы 'ˆ' и '$', то претензия 'ˆ' будет искать совпадение в начале строки, а претензия '$' будет искать совпадение в конце строки.
#ˆпиво$#m
совапдение - "пиво\n" (в строке 'пиво')
нет совапдения - "пи\nво" (здесь 'пиво' в разных строках)

D - претензия '$' не учитывает [\n]
#шаблон#D
если в шаблоне есть метасимвол '$'.
Претензия '$' будет искать совпадение в фактическом конце текста, игнорируя переводы каретки на новую строку [\n].

A - привязать шаблон к началу текста
#шаблон#A
Будет искать шаблон только в фактическом начале теста.

x - разрешить комментарии: пробел и #
#шаблон#x
здесь в шаблоне разрешены пробел и #, как комментарии, поэтому пробел и # надо предварять слешем, если только они не обозначают комментарии.
/слово
#комментарий
ищу/x
будет искать 'словоищу'. То есть, здесь игнорируются пробелы и все, что следует за знаком диез.

X - воспринимать неверную подстановку как ошибку.
#шаблон#X

S - предварительная оптимизация шаблона
#шаблон#S

e - используется в функции 'preg_replace' для ее активации
#шаблон#e

тоесть в нашем случае это Ui (ищем как можно меньше совпадений, игнорируя регистр)




Функции для работы с регулярными выражениями.


1. в стиле POSIX


ereg() - совпадение с регулярным выражением.

bool ereg(string pattern, string string [, array regs])

Данная функция ищет в строке string соответствие регулярному выражению, заданному в шаблоне pattern. Если соответствия подвыражений с шаблоном будут найдены, то они сохраняются в массиве соответствий regs. При этом $regs[0] содержит копию строки string, $regs[1] содержит подстроку, начинающуюся с первой левой скобки, $regs[2] хранит подстроку, начинающуюся со второй левой скобки и т.д.

Ниже приведен код, преобразующий фразу "Вася любит пиво больше чем Иван" в более лучшую для меня "Иван любит пиво больше чем Вася".

пример:

PHP
  1.  
  2. <?php
  3.  
  4. $text = "Вася любит пиво больше чем Иван";
  5.  
  6. if (ereg ("(Вася) (любит пиво больше чем) (Иван)", $text, $regs)):
  7. echo "{$regs[3]} {$regs[2]} {$regs[1]}";
  8. else:
  9. echo "Алкоголики не найдены";
  10. endif;
  11. ?>
  12.  


Этот пример даст:
Иван любит пиво больше чем Вася



ereg_replace() - замещает регулярное выражение.

string ereg_replace(string pattern, string replacement, string string)

Эта функция заменяет найденный в строке string шаблон pattern на строку replacement и, если соответствие было найдено, возвращает модифицированную строку.

пример:
PHP
  1.  
  2. <?php
  3. $text = "Вася любит пиво больше чем Иван";
  4. echo ereg_replace("пиво", "водку", $text);
  5. ?>
  6.  


Этот пример даст:
Вася любит водку больше чем Иван



split() - делает из строки массив с помощью регулярного выражения.

array split (string pattern, string string [, int limit])

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

Эта функция полезна при разделении дат, доменных имен и т.д.

пример:
PHP
  1.  
  2. <?php
  3. $text = "пиво.дефки.рок";
  4. $array = split (".", $text);
  5. print_r($array);
  6. ?>
  7.  


Этот пример даст:
Array ( [0] => пиво [1] => дефки [2] => рок )




2. Perl-совместимые регулярные выражения



preg_match() - выполняет подстановку регулярного выражения.

int preg_match (string pattern, string subject [, array matches])

Эта функция ищет в строке subject соответствие регулярному выражению pattern. Если задан необязательный параметр matches, то результаты поиска помещаются в массив

пример:
PHP
  1.  
  2. <?php
  3. $str = "Вася любит пиво и Иван любит пиво";
  4.  
  5. // пиво есть
  6. if (preg_match ("#пиво#i", $str)):
  7. echo("слово пиво втречается");
  8. else:
  9. echo("слово пиво не втречается");
  10. endif;
  11.  
  12. // водки нет
  13. if (preg_match ("#водка#i", $str)):
  14. echo("слово водка втречается");
  15. else:
  16. echo("слово водка не втречается");
  17. endif;
  18.  
  19. ?>
  20.  


Этот пример даст:
слово пиво втречаетсяслово водка не втречается


с добавлением необязательного параметра matches
пример:
PHP
  1.  
  2. <?php
  3. $url = "http://www.phpforum.ru";
  4. preg_match("/^(http://)?([^/]+)/i", $url, $matches);
  5. print_r($matches);
  6. ?>
  7.  


Этот пример даст:
Array ( [0] => http://www.phpforum.ru [1] => http:// [2] => www.phpforum.ru )




preg_match_all() - выполняет глобальный поиск совпадения регулярного выражения.

int preg_match_all (string pattern, string subject, array matches [, int flags])

Ищет в subject все совпадения с регулярным выражением pattern и помещает их в matches в порядке, специфицированном в order.

После нахождения первого совпадения последующий поиск продолжается до нахождения последнего совпадения.

пример:
PHP
  1.  
  2. <?php
  3. $text = "<b>Вася</b> любит <b>пиво</b> больше чем <b>Иван</b>";
  4. preg_match_all ("#<b>(.*)</b>#iU", $text, $regs);
  5. echo "<pre>";
  6. print_r($regs[1]);
  7. ?>
  8.  

Этот пример даст:
Array
(
[0] => Вася
[1] => пиво
[2] => Иван
)





preg_replace() - выполняет поиск и замену регулярного выражения.

mixed preg_replace (mixed pattern, mixed replacement, mixed subject [, int limit])

Ищет в subject совпадения с pattern и замещает их replacement. Если limit специфицирован, то замещаются только limit совпадений; если limit опущен или равен -1, замещаются все совпадения.

Replacement может содержать ссылку в форме \\n или $n, где последняя форма предпочтительнее. Каждая такая ссылка замещается текстом, захваченным n'ным патэрном в скобках. n может быть от 0 до 99, а \\0 или $0 ссылаются на текст, совпавший со всем патэрном. Открывающие скобки подсчитываются слева направо (начиная с 1) для получения количества захватывающих субпатэрнов.

Если совпадения найдены, возвращается новый subject, иначе subject возвращается без изменений.

Каждый параметр preg_replace() может быть массивом.

Если subject это массив, то поиск и замена выполняются в каждом вхождении subject, return-значение также будет массивом.

Если pattern и replacement являются массивами, то preg_replace() принимает значение из каждого массива и использует их для выполнения поиска и замены в subject. Если replacement имеет меньше значений, чем pattern, то для оставшихся значений для замены используется пустая строка. Если pattern это массив, а replacement это строка, то эта замещающая строка используется для каждого значения pattern. Обратное не будет иметь смысла.

Модификатор /e делает так, что preg_replace() рассматривает параметр replacement как PHP-код после выполнения соответствующей замены ссылок

пример:
PHP
  1.  
  2. <?php
  3. $text = "<b>Вася</b> любит <b>пиво</b> больше чем <b>Иван</b>";
  4. echo preg_replace("#<b>(.*)</b>#iU","[замена]", $text);
  5. ?>
  6.  


Этот пример даст:
[замена] любит [замена] больше чем [замена]

пример:
PHP
  1.  
  2. <?php
  3. $text = "<b>Вася</b> любит <b>пиво</b> больше чем <b>Иван</b>";
  4. $search = array ("'Вася'i", "'пиво'i","'Иван'i");
  5. $replace = array ( "Катя","мороженное","Маша");
  6. echo preg_replace ($search, $replace, $text);
  7. ?>
  8.  


Этот пример даст:
Катя любит мороженное больше чем Маша


пример:
PHP
  1.  
  2. <?php
  3. $text = "<b>Вася</b> любит <b>пиво</b> больше чем <b>Иван</b>";
  4. echo preg_replace ("#<b>(.*)</b>#iUe", "md5('1')",$text);
  5. ?>
  6.  


Этот пример даст:
b212e4e8bc960592ff6571ffa6000a67 любит 07564df0646634634ddece185c65f5fc больше чем ff4650ffb21f59efd09de0193d8a928c


....пока всё не могу уже... 9 утра а я ночь не спал... потом дополню и отвформатирую
Zenith
Hi!
А как же функция implode () ?
string implode ( string glue, array pieces )
Возвращает строку, полученную объединением строковых представлений элементов массива pieces, со вставкой строки glue между соседними элементами.

имхо split() наоборот smile.gif

_____________
"Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете". (с) Макконнелл, "Совершенный код".
theflame
Есть вопрос. Может подскажите. Пытаюсь найти такую банальную функцию (или метод), которая бы возвращала мне подстроку из строки по заданной маске.

Допустим в строке

</td></tr><tr><td class="num">3.</td><td class="cmp"><input type="checkbox"

мне нужно выделить только подстроку

3.

Чем или как это сделать с помощью инструментов РНР?

Спасибо
baston
Цитата (theflame @ 17.02.2010 - 21:15)
Допустим в строке

</td></tr><tr><td class="num">3.</td><td class="cmp"><input type="checkbox"

мне нужно выделить только подстроку

3.

Как пример (c помощью регулярки):
$str = '</td></tr><tr><td class="num">3.</td><td class="cmp"><input type="checkbox"';
preg_match ("#[\d]+\.#", $str, $res);
echo $res[0];
twin
strip_tags() smile.gif

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

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Настаивал, настаиваю и буду настаивать на своем. На кедровых орешках.

user posted image
theflame
2 baston
Спасибо. А я никак не мог человеческим языком понять описание к этой функции. Ещё примеры дурацкие. Думал уже массивом через preg_split

2 strip_tags
Это я видел, спасибо. Даже думал про неё, но мне местами нужны и теги, точнее ссылки. А я так понимаю, что после обработки этой функцией остаётся только текст. Ведь и его тоже нужно потом как-то резать.
theflame
Так, ну это ладно ) Вот теперь бы как раз с регулярными разобраться )

Чё-то по-проще задачи получалось решать, а тут ступор какой-то. В принципе реально вычленить подстроку, перед которой паттерн1 и после которой паттерн2 ? Или это не регулярные, а работа со строками?

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

$pattern1 = "#!((^$pattern_begin_1|$pattern_begin_2)*($pattern_end_1|$pattern_end_2$))#";

Но херня это, я так понимаю.
theflame
Ладно, попробую ещё разик

Предположим, есть строка
сaсbCCdefс

Каким паттерном из неё можно вычленить подстроку "СC", не зная самой строки, но зная, что она находится между "сb" и "de" ?
twin
<?php

$string = 'сaсbCCdefс';
preg_match("#сb(.+?)de#i", $string, $out);
echo $out[1];


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

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Настаивал, настаиваю и буду настаивать на своем. На кедровых орешках.

user posted image
theflame
Спасибо )

Пока не понял логику, но работает. ) А я уже функцию написал, которая по двум паттернам вырезает то, что между ними ) Ладно, буду думать
horror
хорошая статья, но все же у меня не получается =(

Как мне достать значения со ссылки?

$1 = "http://vkontakte.ru/video11947452_143730565"

Мне с этой ссылки нужно получить два значения:
Переменную1,переменную2

http://vkontakte.ru/video(переменная1)_(переменная2)
хелп sad.gif
olgatcpip
единственное что хочется заметить, так это не увлекайтесь регулярками. Если есть функции чем можно аменить, то лучше использовать их.

Ресурсы жреееет....

_____________
Ласковое слово и кошке приятно... Плюсик в карму сойдет wink.gif
*smarty дока - новая любовь
Моё рукотворение ругайте, хвалите smile.gif
Веду маленький блог
в этом блоге публикую новые работы
WMR217126627282 wink.gif

FatCat
Цитата (horror @ 15.05.2010 - 03:37)
Переменную1,переменную2

$num1 = intval( substr($1, (strpos($1,"video")+5) ) );
$num2 = intval( substr($1, (strpos($1,"_")+1) ) );



Цитата (olgatcpip @ 15.05.2010 - 08:20)
Ресурсы жреееет...

Угумс!
Все руки не доходят сделать свой набор функций, делающих то же, что регулярки, только через substr и strpos.
Пока писал только конкретные реализации; на круг экономия ресурсов выходила на 2 порядка.

_____________
Бесплатному сыру в дырки не заглядывают...
DedMorozzz
Ненаю, ненаю. Мне регулярные выражения очень симпатизируеют...у них такая харизма...

_____________
Если не говорить пользователям, что Linux это "Сложно и страшно", то им совершенно всё равно, в чём не разбираться
olgatcpip
DedMorozzz, когда увидишь ошибку - нет места, память заср..на, а вариант увеличить в лоб не покатит, прочувствуешь скорбь, кою я еле пержила....

_____________
Ласковое слово и кошке приятно... Плюсик в карму сойдет wink.gif
*smarty дока - новая любовь
Моё рукотворение ругайте, хвалите smile.gif
Веду маленький блог
в этом блоге публикую новые работы
WMR217126627282 wink.gif

Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.