Примеры часто используемых регулярных выражений |
Статьи - PHP программирование |
Получить расширение файла preg_replace("/.*?\./", '', 'photo.jpg');
Взять то, что находится между тегами <title> и </title> if (preg_match('|<title.*?>(.*)</title>|sei', $str, $arr)) $title = $arr[1]; Обратите внимание: берется не нулевой элемент массива, а первый! Найти текст, заключенный в какой-то тег и заменить его на другой тег Например: <TITLE> ... </TITLE> заменить аналогично на <МОЙ_ТЕГ> ... </МОЙ_ТЕГ> в HTML-файле: preg_replace("!<title>(.*?)</title>!si","<МОЙ_ТЕГ>\\1</МОЙ_ТЕГ>",$string);
Проверяем, является ли переменная числом if (!preg_match("|^[\d]+$|", $var)) ...
Запретим пользователю использовать в своем имени любые символы, кроме букв русского и латинского алфавита, знака "_" (подчерк), пробела и цифр: if (preg_match("/[^(\w)|(\x7F-\xFF)|(\s)]/",$username)) {
Проверка адреса e-mail Для поля ввода адреса e-mail добавим в список разрешенных символов знаки "@" и "." и "-", иначе пользователь не сможет корректно ввести адрес. Зато уберем русские буквы и пробел: if (preg_match("/[^(\w)|(\@)|(\.)|(\-)]/",$usermail)) {
Проверка на число if(preg_match('/^\d+$/', $var)) echo $var;
Проверка имени файла if (preg_match("/(^[a-zA-Z0-9]+([a-zA-Z\_0-9\.-]*))$/" , $filename)==NULL) {
Проверка расширения файла Архивы (zip, rar, ...) /\.(?:z(?:ip|[0-9]{2})|r(?:ar|[0-9]{2})|jar|bz2|gz|tar|rpm)$/i Аудио (mp3, wav, ...) /\.(?:mp3|wav|og(?:g|a)|flac|midi?|rm|aac|wma|mka|ape)$/i Программы (exe, xpi, ...) /\.(?:exe|msi|dmg|bin|xpi|iso)$/i Изображения (jpg, png, ...) /\.(?:jp(?:e?g|e|2)|gif|png|tiff?|bmp|ico)$/i Видео (mpeg, avi, ...) /\.(?:mpeg|ra?m|avi|mp(?:g|e|4)|mov|divx|asf|qt|wmv|m\dv|rv|vob|asx|ogm)$/i
Выборка цен Часто возникает проблема по парсингу интересующих программиста данных из HTML, который не всегда хорошего качества, все было бы терпимо, если бы еще не вставки на javascript'е, вот пример такого текста: <TD>20.02<BR>05:30 <TD class=l>Товар 1<BR>Товар Те цифры, которые написаны через точку, являются ценами. Задача состоит в том, чтобы собрать все цены, которые находятся между тегами <a>... </a> Видим, что помимо цен между заданными тегами, есть такие, которые идут сразу после тега <TD>, а также стоят между тегами <B>...</B>. Ясно, что описать достаточно точно содержимое атрибутов тега <A> представляется задачей не самой легкой, поэтому надо ее упростить! Любой тег имеет закрывающий знак '>', наша задача описать, что этот знак идет перед ценой, но так как перед ценой может стоять тег <B> и тег <TD>, но эти цены нам не нужны. Каким образом мы узнаем, что цена стоит между тегами <A>...</A>? По тегу, который идет после цены, если это не тег </B>, то это будет либо тег </A> либо <BR>, а так же по тегу перед ценой если этот тег <TD>. Путем таких размышлений мы пришли к выводу, что должно стоять справа, а что должно стоять слева искомой строки, которая описывается как цифры, разделенные точкой: \d*\.\d* То, что должно совпасть слева, мы описали как символ '>', записываем: (?<=>) - выглядит немного странно, но совпадение справа записывается вот так (?<=), а внтури него после ?<= идет символ '>' То, что должно совпасть справа описывается (?=) внутри мы пишем </A>. Теперь опишем, что не должно стоять перед ценой: (?<!<TD>) перед ценой не должен стоять тег <TD>, это и есть негативная ретроспективная проверка. При помощи негативной опережающей проверки опишем, что не должно стоять справа цены: (?!<\/B>) справа от цены не должен стоять тег </B>. Результирующее регулярное выражение, которое описывает все приведенные условия выглядит вот так: preg_match_all("/(?<!<TD>)(?<=>)\d*\.\d*(?!<\/B>)(?=<\/A>)/", $string, $matches); После рассмотрения первого примера стоит сделать замечания и пояснения по поводу использования позиционных проверок. 1. Написанные друг за другом проверки применяются независимо друг от друга в одной точке, не меняя ее. Естественно, что совпадение будет найдено, если все проверки совпадут. В нашем примере это были точки перед и после цены. С точки зрения логики применения проверок нет никакой разницы, будет ли стоять проверка на тег <TD> перед проверкой на знак '>'. Правда, с точки зрения оптимизации первой позиционной проверкой должна идти та, которая имеет наибольшую вероятность несовпадения. 2. Совпавшие значения ретроспективных проверок не сохраняются. Т.е. если в нашем примере совпадает опережающая проверка, которая указывает, что после цены идет тег </A>, то сам тег </A>, который заключен в конструкцию (?=) не будет запоминаться в специальных перменных /1,/2 и т.д. Сделано это из-за того, что позиционная проверка совпадает не со строкой, а с местом в строке (она описывает место, где произошло совпадение, а не символы, которые совпали). 3. Нужно указать что PCRE не позволяет делать проверки на совпадение текста произвольной длинны. То есть нельзя делать, например, такую проверку: /(?<=\d+) Механизм поиска совпадения в ретроспективной проверке реализован так, что при поиске механизму должна подаваться строка фиксированной длины, для того, чтобы в случае несовпадения, механизм мог вернуться назад на фиксированое количество символов и продолжить поиск совпадений в других позиционных проверках. Думаю, что сразу это понять сложно, но представьте себе как происходит поиск совпадения в части (?)(?<=>) вышеописанного регулярного выражения. Берется строка, в которой происходит поиск, отсчитывается от начала столько символов, сколько символов будет в совпадении позиционной проверки, в нашем варианте это 4: <, T, D, > с этого места происходит "заглядывание назад" (ретроспективные проверки на английском языке звучит как lookbhind assertions), т.е. все предыдущие 4 символа проверяются на совпадение со строкой <TD>, если механизм не нашел совпадения, то ему надо вернуться на 4 символа назад, выполнить тоже самое с проверкой (?<=>), т.е. отсчитать один символ, "заглянуть" назад, попробовать найти проверку предыдущего символа с символом '>'. Представьте себе, что условие совпадения состоит из строки нефиксированной длинны: (??) подобная запись должна означать, что перед ценой, не должен стоять тег <TD> в количестве максимимум один экземпляр (либо вообще не стоять). Вот и получается, что после того, как механизм отсчитает 4 символа от начала, он проверит на совпадение с <TD>, но в условии указано, что тега может и не быть вообще, тогда возникает вопрос, на сколько знаков верунться назад, чтобы проверить на совпадение другие проверки. На 4 или вообще не возвращаться? Сразу возникает вопрос, а зачем идти вперед, чтобы потом "заглянуть" назад? Делается это для того, чтобы в случае совпадения всех проверок сразу же начать проверку тех символов, которые идут после позиционных проверок.
Выбрать все изображения со страницы Как-то мне нужно было получить все изображения, которые использовались на сайте. Что для этого надо сделать? Правильно, надо в браузере нажать на "Сохранить как", указать куда сохранить страницу. Появится файл с исходным кодом страницы и папка с изображениями. Но вы никогда не сохраните в эту папку изображения, которые прописаны в стилях объектов по крайней мере в эксплорере: style="background-image:url(/editor/em/Unlink.gif);" Для проведения вышеописанной операции надо: Начнем с простого. Символы латинского алфавита, цифры, точка и слеш описываются символьным классом: [a-z.\/] их может быть сколько угодно, на самом деле больше 3 (имя файла, минимум один символ, точка, расширение, минимум один символ), но в данном случае, зная контекст, это некритично, поэтому указываем квантификатор * [a-z.\/]* Слева должны идти 'url(' и мы это описываем при помощи позитивной ретроспективной проверки: (?<=url() Но обратите внимание на то, что скобка в регулярных выражениях является спецсимволом группировки, поэтому чтобы она стала символом, надо перед ней поставить другой спецсимвол - слеш. (?<=url\() Справа от относительного пути должна стоять закрывающаяся круглая скобка. Это условие описывается при помощи позитивной опережающей проверки: (?=\)) Как видите, перед одной из скобок стоит слеш, что означает, что она интепретируется не как спецсимвол, а как литерал. Ниже приведен полный код на PHP, который выполняет все действия, кроме вопроса о разрешении использовать контент: preg_match_all("/(?<=url\()[a-z.\/]*(?=\))/i", $content, $matches);
Парсер всех внешних и внутренних ссылок со страницы В массиве $vnut только ссылки внутренние, в массиве $vnech только внешние ссылки. $html=file_get_contents ('http://www.popsu.net');
Является ли строка числом, длиной до 77 цифр: if (preg_match("/^[0-9]{1,77}$/",$string)) echo "ДА";
Состоит ли строка только из букв, цифр и "_", длиной от 8 до 20 символов: if (preg_match("/^[a-zа-я0-9_]{8,20}$/",$string)) echo "yes"; else echo "no";
Проверка строки на допустимость Есть ли в строке любые символы, кроме допустимых. Допустимыми считаются буквы, цифры и "_". Длину тут проверять нельзя, разве что просто дополнительным условием strlen($string). Не путайте с предыдущим примером - хоть результат и одинаковый, но метод другой, "от противного" if ( ! preg_match("/[^a-zа-я0-9_]/",$string)) Для регистро независимого сравнения используйте preg_match с модификатором i(). Проверка повторяющихся символов Есть ли в строке идущие подряд символы, не менее 3-х символов подряд (типа "абвгДДДеё", но не "ааббаабб"): if (preg_match("/(.)\\1\\1/",$string)) echo "yes"; else echo "no";
Заменить везде в тексте СТРОКУ1 на СТРОКУ2 (задача решается без регулярных выражений): $string=str_replace("СТРОКА1","СТРОКА2",$string);
Заменить кривые коды перехода строки на нормальные: для этого нужно только удалить "\r". Переходы бывают нормальными (но разными!): "\n" или "\r\n". Еще бывают глюки, типа "\r\r\n". $string=str_replace("\r","",$string);
Заменить все повторяющиеся пробелы на один Не пытайтесь здесь применить str_replace, это хорошая функция, но не для данного примера. $string=preg_replace("/ХХ+/","Х",$string); // вместо Х поставьте пробел
Удаление многократно повторяющихся знаков препинания Удаление знаков препинания, которые повторяются больше 3 раз, т.е. !!!!! -> !!!, ????? -> ??? и т.д. Заменяются следующие символы: . ! ? ( ) $text = preg_replace('#(\.|\?|!|\(|\)){3,}#', '\1\1\1', $text);
Сложная замена В тексте есть некоторые слова, допустим "СЛОВО" и "ЛЯЛЯЛЯ" (и т.д.), которые нужно одинаковым образом заменить на тоже самое, но с добавками. Возможно, слова отсутствуют или встречаются много раз в любом регистре. Т.е. если было "слово" или "СлОвО" (или еще как), нужно заменить это на "<b>слово</b>" или "<b>СлОвО</b>" (смотря, как было). Другими словами нужно найти перечень слов в любом регистре и вставить по краям найленных слов фиксированные строки (на "<b>" и "</b>"). $string=preg_replace("/(слово1|слово2|ляляля|слово99)/si","<b>\\1</b>",$string);
Проверка URL на корректность Поддерживает все, что только может быть в УРЛ... Помните о том, что вы должны не только проверять, но и принимать новое значение от функции, т.к. та дописывает "http://" в случае его отсутствия. // функция для удаления опасных сиволов Таким образом для проверки нужно использовать нечто такое: $url=checkurl($url); // перезаписали УРЛ в самого себя
preg_match("/abc/", $string); // Returns true if "abc" is found at the beginning of $string. preg_match("/^abc/", $string); // Returns true if "abc" is found at the end of $string. preg_match("/abc$/", $string); Возвращает true если browser = Netscape 2, 3 or MSIE 3. preg_match("/(ozilla.[23]|MSIE.3)/i", $_SERVER["HTTP_USER_AGENT"]); // Places three space separated words into $regs[1], $regs[2] and $regs[3]. preg_match("/([[:alnum:]]+) ([[:alnum:]]+) ([[:alnum:]]+)/i", $string, $regs); Добавить <br /> в начало всех строк $string = preg_replace("/^/", " Добавить <br /> в конец всех строк $string = preg_replace("/$/", " // Get rid of any newline characters in $string. $string = preg_replace("/\n/", "", $string); Удалить все аттрибуты у всех тегов, кроме a, p, img preg_replace("/<([^ap(img)].*?)\s.*?>/is", "<\\1>", $string); Выбрать локальные URL Как можно выбрать не просто все урлы в HTML странице а те которые не начинаются на http://, другими словами локальные. preg_match_all("#\s(?:href|src|url)=(?:[\"\'])?(.*?)(?:[\"\'])?(?:[\s\>])#i", $buffer, $matches); Выбрать все параметры: $string = '<table border=\'0\' cellpadding = "0" cellspacing=0 style= "border-collapse: collapse">'; Array ( [0] => Array ( [0] => border='0' [1] => cellpadding = "0" [2] => cellspacing=0 [3] => style= "border-collapse: collapse" ) [1] => Array ( [0] => border [1] => cellpadding [2] => cellspacing [3] => style ) [2] => Array ( [0] => '0' [1] => "0" [2] => 0 [3] => "border-collapse: collapse" ) [3] => Array ( [0] => 0 [1] => 0 [2] => [3] => border-collapse: collapse ) [4] => Array ( [0] => [1] => [2] => 0 [3] => ) ) Конвертор HTML в текст // $document на выходе должен содержать HTML-документ.
Найти и заменить все "http://" на ссылки
Вариант 1: $text = preg_replace('#(?<!\])\bhttp://[^\s\[<]+#i',
Вариант 2, с выделением домена: // Cuts off long URLs at $url_length, and appends "..."
Еще один вариант, учитывающий "WWW." // match protocol://address/path/file.extension?some=variable&another=asf%
Разбор адесов E-mail. $text = "Адреса:
Данный адрес e-mail защищен от спам-ботов, Вам необходимо включить Javascript для его просмотра.
,
Данный адрес e-mail защищен от спам-ботов, Вам необходимо включить Javascript для его просмотра.
."; То же самое, но немножко по-другому: $html = preg_replace( '/(\S+)@([a-z0-9.-]+)/is', '<a href="mailto:$0">$0</a>', $text);
Проверить, что в строке есть число (одна или более цифра) preg_match('/(\d+)/s', "article_123.html", $pockets);
Найти в тексте адрес E-mail // \S означает "не пробел", а [a-z0-9.]+ -
Превращение E-mail в HTML-ссылку. $text = "Привет от
Данный адрес e-mail защищен от спам-ботов, Вам необходимо включить Javascript для его просмотра.
, а также от
Данный адрес e-mail защищен от спам-ботов, Вам необходимо включить Javascript для его просмотра.
!";
Простейший разбор даты. $str = " 15-16/2000 "; // к примеру
Замена по шаблону $text = htmlspecialchars(file_get_contents(__FILE__));
Обратные ссылки $str = "Hello, this <b>word</b> is bold!";
"Жадные" квантификаторы $str = "Hello, this <b>word</b> is <b>bold</b>!";
Сравнение "жадных" и "ленивых" квантификаторов $str = '[b]жирный текст [b]а тут - еще жирнее[/b] вернулись[/b]';
Многострочность. $str = file_get_contents(__FILE__);
Использование PREG_OFFSET_CAPTURE $st = '<b>жирный текст</b>';
Применение preg_grep() foreach (preg_grep('/^ex\d/s', glob("*")) as $fn)
Различные флаги preg_match_all() Header("Content-type: text/plain");
preg_replace_callback() // Пользовательская функция. Будет вызываться для каждого
Получение строки GET-запроса. Для начала поставим самую простую задачу - получить часть URL, содержащую GET-параметры. function ggp($url) { // get GET-parameters string Не стоит забывать, что адрес может вовсе не содержать никакого GET-запроса, и массив вхождений может не иметь второго элемента 3. Исключение GET-запроса из URL. Иногда нужно получить URL без GET-параметров (например, при перенаправлении запросов с помощью mod_rewrite зачастую требуется проводить анализ URL, чтобы сформировать ответ клиенту; нередко для анализа нужна только статическая часть URL, а часть, где передается GET-запрос, не нужна и даже мешает). // удаление GET-параметров из URL заменить все символы кроме чисел и запятой на '' $value = preg_replace('/[^\d,]+/', '', $value); // заменить все символы кроме чисел и запятой на ''
Есть ли в строке параметров сессия (PHPSESSID): print $_SERVER['REQUEST_URI'].'<br>'; Удалить из строки параметр page и добавить другой page. Этот пример позволяет заменить один параметр на другой не испортив все остальные параметры строки. Если Вы найдете более оптимальное решение, присылайте. $href1=str_replace('&&','&',str_replace('?&','?',preg_replace("/&*page=([0-9]{1,3})&*/i", '&', $_SERVER['REQUEST_URI']))); Проверка формата времени. date: mm:hh. $time = "10:11"; Как вытащить слова из текста? Это регулярное выражение PHP разбирает текст на отдельные слова, основываясь на определении: слово - это непрерывная последовательность букв английского или русского алфавитов. $x="Типа, %^& читайте___люди~~~~__маны__ На... РУССКОМ!! Будете+здоровы. abc, qwe, zxc"; Результат будет таким: Типа читайте люди маны На РУССКОМ Будете здоровы abc qwe zxc
Как заставить работать с русскими буквами в UTF-8? В PHP это решается вот так: preg_replace("/[^\p{L}0-9\+\-\_:\.@ ]/u", "", $_string)); \p{L} = все буквы |