Search
Write a publication
Pull to refresh

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

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

Получить расширение файла



preg_replace("/.*?\./", '', 'photo.jpg');

Взять то, что находится между тегами и



if (preg_match('|<title.*?>(.*)|sei', $str, $arr)) $title = $arr[1];
else $title='';

Обратите внимание: берется не нулевой элемент массива, а первый!
Если title будет встречаться несколько раз, то будет вырезано от первого и до последнего!

Найти текст, заключенный в какой-то тег и заменить его на другой тег


Например: … заменить аналогично на <МОЙ_ТЕГ>… </МОЙ_ТЕГ> в HTML-файле:

preg_replace("!(.*?)!si","<МОЙ_ТЕГ>\\1</МОЙ_ТЕГ>",$string);


Проверяем, является ли переменная числом



if (!preg_match("|^[\d]+$|", $var)) ...

Запретим пользователю использовать в своем имени любые символы, кроме букв русского и латинского алфавита, знака "_" (подчерк), пробела и цифр:



if (preg_match("/[^(\w)|(\x7F-\xFF)|(\s)]/",$username)) {
echo "invalid username";
exit;
}


Проверка адреса e-mail


Для поля ввода адреса e-mail добавим в список разрешенных символов знаки "@" и "." и "-",
иначе пользователь не сможет корректно ввести адрес. Зато уберем русские буквы и пробел:
if (preg_match("/[^(\w)|(\@)|(\.)|(\-)]/",$usermail)) {
echo "invalid mail";
exit;
}


Проверка на число


if(preg_match('/^\d+$/', $var)) echo $var;


Проверка имени файла



if (ereg("(^[a-zA-Z0-9]+([a-zA-Z\_0-9\.-]*))$" , $filename)==NULL) {
echo "invalid filename";
exit;
}


Проверка расширения файла


Архивы (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


Выбрать все изображения со страницы


Как-то мне нужно было получить все изображения, которые использовались на
сайте. Что для этого надо сделать? Правильно, надо в браузере нажать на
«Сохранить как», указать куда сохранить страницу. Появится файл с исходным кодом
страницы и папка с изображениями. Но вы никогда не сохраните в эту папку
изображения, которые прописаны в стилях объектов по крайней мере в эксплорере:



style="background-image:url(/editor/em/Unlink.gif);"

Для проведения вышеописанной операции надо:
1. попросить хозяина хоста использовать контент, размещенный на его сайте.
2. найти в тексте все строки, подобные приведенной выше, и выделить в них относительный путь к файлу
3. сформировать файл в котором будут выводиться изображения при помощи:

Делаем: В переменную $content получаем исходный код страницы. А дальше используя
регулярные выражения ищем относительные пути, которые прописаны в стилях. Каждый
раз, когда я описываю, как я реализовал пример, я сначала тщательно описываю,
что ищем, и тщательно описываю, в каком контексте происходит поиск.
Проанализировав исходный код страницы стало понятно, что кроме как в описании
стилей относительные пути к изображениям нигде не используются. Слева от
относительного пути идет последовательность символов: url( Справа от
относительного пути стоит закрывающаяся круглая скобка. Между этими
последовательностями символов могут быть буквы латинского алфавита, цифры и
слеши, а также точка перед расширением файла.



Начнем с простого. Символы латинского алфавита, цифры, точка и слеш описываются символьным классом: [a-z.\/]
их может быть сколько угодно, на самом деле больше 3 (имя файла, минимум один
символ, точка, расширение, минимум один символ), но в данном случае, зная
контекст, это некритично, поэтому указываем квантификатор * [a-z.\/]* Слева
должны идти 'url(' и мы это описываем при помощи позитивной ретроспективной
проверки: (?<=url() Но обратите внимание на то, что скобка в регулярных
выражениях является спецсимволом группировки, поэтому чтобы она стала символом,
надо перед ней поставить другой спецсимвол — слеш. (?<=url\() Справа от
относительного пути должна стоять закрывающаяся круглая скобка. Это условие
описывается при помощи позитивной опережающей проверки: (?=\)) Как видите, перед
одной из скобок стоит слеш, что означает, что она интепретируется не как
спецсимвол, а как литерал. Ниже приведен полный код на PHP, который выполняет
все действия, кроме вопроса о разрешении использовать контент:



preg_match_all("/(?<=url\()[a-z.\/]*(?=\))/i", $content, $matches);
foreach($matches[0] as $item)
{ echo ""; }


Парсер всех внешних и внутренних ссылок со страницы


В массиве $vnut только ссылки внутренние, в массиве $vnech только внешние ссылки.
$html=file_get_contents ('http://www.popsu.net');
$url='popsu.net';
$vnut=array();
$vnech=array();
preg_match_all('~<a [^<>]*href=[\'"]([^\'"]+)[\'"][^<>]*>(((?!~si',$html, $matches);
foreach ($matches[1] as $val) {
if (!preg_match("~^[^=]+://~", $val) || preg_match("~^[^://]+://(www\.)?".$url."~i", $val)) { $vnut[]=$val; }
else $vnech[]=$val;
}
$vnut=array_unique ($vnut);
$vnech=array_unique ($vnech);
print_r ($vnut);
print_r ($vnech);


Является ли строка числом, длиной до 77 цифр:



if (ereg("^[0-9]{1,77}$",$string)) echo "ДА";


Состоит ли строка только из букв, цифр и "_", длиной от 8 до 20 символов:



if (ereg("^[a-zа-я0-9_]{8,20}$",$string)) echo "yes"; else echo "no";


Проверка строки на допустимость


Есть ли в строке любые символы, кроме допустимых. Допустимыми считаются
буквы, цифры и "_". Длину тут проверять нельзя,
разве что просто дополнительным условием strlen($string). Не путайте с предыдущим
примером — хоть результат и одинаковый, но метод другой, «от противного»
:)

if ( ! ereg("[^a-zа-я0-9_]",$string))
echo "нет посторонних букв (OK)";
else
echo "есть посторонние буквы (FALSE)";

Для регистро независимого сравнения используйте eregi().

Проверка повторяющихся символов


Есть ли в строке идущие подряд символы, не менее 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);


Сложная замена


В тексте есть некоторые слова, допустим «СЛОВО» и «ЛЯЛЯЛЯ» (и т.д.),
которые нужно одинаковым образом заменить на тоже самое, но
с добавками. Возможно, слова отсутствуют или встречаются много раз
в любом регистре.
Т.е. если было «слово» или «СлОвО» (или еще как),
нужно заменить это на "слово" или "СлОвО" (смотря, как было).
Другими словами нужно найти перечень слов в любом регистре и вставить
по краям найленных слов фиксированные строки (на "" и "").

$string=preg_replace("/(слово1|слово2|ляляля|слово99)/si","\\1",$string);


Проверка URL на корректность


Поддерживает все, что только может быть в УРЛ…
Помните о том, что вы должны не только проверять, но и принимать новое значение
от функции, т.к. та дописывает «http://» в случае его отсутствия.
// функция для удаления опасных сиволов
function pregtrim($str) {
return preg_replace("/[^\x20-\xFF]/","",@strval($str));
}

//
// проверяет URL и возвращает:
// * +1, если URL пуст
// if (checkurl($url)==1) echo "пусто"
// * -1, если URL не пуст, но с ошибками
// if (checkurl($url)==-1) echo "ошибка"
// * строку (новый URL), если URL найден и отпарсен
// if (checkurl($url)==0) echo "все ок"
// либо if (strlen(checkurl($url))>1) echo "все ок"
//
// Если протокола не было в URL, он будет добавлен ("http://")
//
function checkurl($url) {
// режем левые символы и крайние пробелы
$url=trim(pregtrim($url));
// если пусто - выход
if (strlen($url)==0) return 1;
//проверяем УРЛ на правильность
if (!preg_match("~^(?:(?:https?|ftp|telnet)://(?:[a-z0-9_-]{1,32}".
"(?::[a-z0-9_-]{1,32})?@)?)?(?:(?:[a-z0-9-]{1,128}\.)+(?:com|net|".
"org|mil|edu|arpa|gov|biz|info|aero|inc|name|[a-z]{2})|(?!0)(?:(?".
"!0[^.]|255)[0-9]{1,3}\.){3}(?!0|255)[0-9]{1,3})(?:/[a-z0-9.,_@%&".
"?+=\~/-]*)?(?:#[^ '\"&<>]*)?$~i",$url,$ok))
return -1; // если не правильно - выход
// если нет протокала - добавить
if (!strstr($url,"://")) $url="http://".$url;
// заменить протокол на нижний регистр: hTtP -> http
$url=preg_replace("~^[a-z]+~ie","strtolower('\\0')",$url);
return $url;
}

Таким образом для проверки нужно использовать нечто такое:

$url=checkurl($url); // перезаписали УРЛ в самого себя
if ($url) exit("Ошибочный URL");


// Returns true if «abc» is found anywhere in $string.

ereg("abc", $string);


// Returns true if «abc» is found at the beginning of $string.

ereg("^abc", $string);


// Returns true if «abc» is found at the end of $string.

ereg("abc$", $string);


Возвращает true если browser = Netscape 2, 3 or MSIE 3.



eregi("(ozilla.[23]|MSIE.3)", $_SERVER["HTTP_USER_AGENT"]);


// Places three space separated words into $regs[1], $regs[2] and $regs[3].

ereg("([[:alnum:]]+) ([[:alnum:]]+) ([[:alnum:]]+)", $string, $regs);


Добавить
в начало всех строк



$string = ereg_replace("^", "
", $string);


Добавить
в конец всех строк



$string = ereg_replace("$", "
", $string);

// Get rid of any newline characters in $string.

$string = ereg_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 = '

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-документ.
// Необходимо удалить все HTML-теги, секции javascript,
// пробельные символы. Также необходимо заменить некоторые
// HTML-сущности на их эквивалент.

$search = array ("'<script[^>]*?>.*?'si", // Вырезает javaScript
"'<[\/\!]*?[^<>]*?>'si", // Вырезает HTML-теги
"'([\r\n])[\s]+'", // Вырезает пробельные символы
"'&(quot|#34);'i", // Заменяет HTML-сущности
"'&(amp|#38);'i",
"'&(lt|#60);'i",
"'&(gt|#62);'i",
"'&(nbsp|#160);'i",
"'&(iexcl|#161);'i",
"'&(cent|#162);'i",
"'&(pound|#163);'i",
"'&(copy|#169);'i",
"'&#(\d+);'e"); // интерпретировать как php-код

$replace = array ("",
"",
"\\1",
"\"",
"&",
"<",
">",
" ",
chr(161),
chr(162),
chr(163),
chr(169),
"chr(\\1)");

$text = preg_replace($search, $replace, $document);



Найти и заменить все "http://" на ссылки



Вариант 1:


$text = preg_replace('#(?<!\])\bhttp://[^\s\[<]+#i',
"Посмотреть на сайте",
nl2br(stripslashes($text)));

<br>

Вариант 2, с выделением домена:


// Cuts off long URLs at $url_length, and appends "..."
function reduceurl($url, $url_length) {
$reduced_url = substr($url, 0, $url_length);
if (strlen($url) > $url_length) $reduced_url .= '...';
return $reduced_url;
}

$linktext = preg_replace("#\[(([a-zA-Z]+://)([a-zA-Z0-9?&%.;:/=+_-]*))\]#e", "'' . reduceurl(\"$3\", 30) . ''", $linktext);


Еще один вариант, учитывающий "WWW."
// match protocol://address/path/file.extension?some=variable&another=asf%
$text = preg_replace("/\s(([a-zA-Z]+:\/\/)([a-z][a-z0-9_\..-]*[a-z]{2,6})([a-zA-Z0-9\/*-?&%]*))\s/i", " $3 ", $text);

// match www.something.domain/path/file.extension?some=variable&another=asf%
$text = preg_replace("/\s(www\.([a-z][a-z0-9_\..-]*[a-z]{2,6})([a-zA-Z0-9\/*-?&%]*))\s/i", " $2 ", $text);


Разбор адесов E-mail.


$text = "Адреса: user-first@mail.ru, second.user@mail.ru.";
$html = preg_replace(
'{
[\w-.]+ # имя ящика
@
[\w-]+(\.[\w-]+)* # имя хоста
}xs',
'$0
',
$text
);
echo $html;

То же самое, но немножко по-другому:

$html = preg_replace( '/(\S+)@([a-z0-9.-]+)/is', '$0', $text);


Проверить, что в строке есть число (одна или более цифра)



preg_match('/(\d+)/s', "article_123.html", $pockets);
// Совпадение (подвыражение в скобках) окажется в $pockets[1].
echo $pockets[1]; // выводит 123


Найти в тексте адрес E-mail



// \S означает "не пробел", а [a-z0-9.]+ -
// "любое число букв, цифр или точек". Модификатор 'i' после '/'
// заставляет PHP не учитывать регистр букв при поиске совпадений.
// Модификатор 's', стоящий рядом с 'i', говорит, что мы работаем
// в "однострочном режиме" (см. ниже в этой главе).
preg_match('/(\S+)@([a-z0-9.]+)/is', "Привет от somebody@mail.ru!", $p);
// Имя хоста будет в $p[2], а имя ящика (до @) - в $p[1].
echo "В тексте найдено: ящик - $p[1], хост - $p[2]";


Превращение E-mail в HTML-ссылку.


$text = "Привет от somebody@mail.ru, а также от other@mail.ru!";
$html = preg_replace(
'/(\S+)@([a-z0-9.]+)/is', // найти все E-mail
'$0
', // заменить их по шаблону
$text // искать в $text
);
echo $html;


Простейший разбор даты.


$str = " 15-16/2000 "; // к примеру
$re = '{
^\s*( # начало строки
(\d+) # день
\s* [[:punct:]] \s* # разделитель
(\d+) # месяц
\s* [[:punct:]] \s* # разделитель
(\d+) # год
)\s*$ # конец строки
}xs';
// Разбиваем строку на куски при помощи preg_match().
preg_match($re, $str, $pockets) or die("Not a date: $str");
// Теперь разбираемся с карманами.
echo "Дата без пробелов: '$pockets[1]' <br>";
echo "День: $pockets[2] <br>";
echo "Месяц: $pockets[3] <br>";
echo "Год: $pockets[4] <br>";


Замена по шаблону



$text = htmlspecialchars(file_get_contents(__FILE__));
$html = preg_replace('/(\$[a-z]\w*)/is', '$1', $text);
echo "$html
";


Обратные ссылки


$str = "Hello, this word is bold!";
$re = '|<(\w+) [^>]* > (.*?) </\1>|xs';
preg_match($re, $str, $pockets) or die("Нет тэгов.");
echo htmlspecialchars("'$pockets[2]' обрамлено тэгом '$pockets[1]'");


"Жадные" квантификаторы



$str = "Hello, this word is bold!";
$re = '|<(\w+) [^>]* > (.*) </\1>|xs';
preg_match($re, $str, $pockets) or die("Нет тэгов.");
echo htmlspecialchars("'$pockets[2]' обрамлено тэгом '$pockets[1]'");


Сравнение "жадных" и "ленивых" квантификаторов



$str = '[b]жирный текст [b]а тут - еще жирнее[/b] вернулись[/b]';
$to = '$1';
$re1 = '|\[b\] (.*) \[/b\]|ixs';
$re2 = '|\[b\] (.*?) \[/b\]|ixs';
$result = preg_replace($re1, $to, $str);
echo "Жадная версия: ".htmlspecialchars($result)."<br>";
$result = preg_replace($re2, $to, $str);
echo "Ленивая версия: ".htmlspecialchars($result)."<br>";


Многострочность.



$str = file_get_contents(__FILE__);
$str = preg_replace('/^/m', "\t", $str);
echo "".htmlspecialchars($str)."
";


Использование PREG_OFFSET_CAPTURE



$st = 'жирный текст';
$re = '|<(\w+).*?>(.*?)</\1>|s';
preg_match($re, $st, $p, PREG_OFFSET_CAPTURE);
echo ""; print_r($p); echo "
";


Применение preg_grep()



foreach (preg_grep('/^ex\d/s', glob("*")) as $fn)
echo "Файл примера: $fn<br>";


Различные флаги preg_match_all()


Header("Content-type: text/plain");
$flags = array(
"PREG_PATTERN_ORDER",
"PREG_SET_ORDER",
"PREG_SET_ORDER|PREG_OFFSET_CAPTURE",
);
$re = '|<(\w+).*?>(.*?)</\1>|s';
$text = "текст и еще другой текст";
echo "Строка: $text\n";
echo "Выражение: $re\n\n";
foreach ($flags as $name) {
preg_match_all($re, $text, $pockets, eval("return $name;"));
echo "Флаг $name:\n";
print_r($pockets);
echo "\n";
}


preg_replace_callback()


// Пользовательская функция. Будет вызываться для каждого
// совпадения с регулярным выражением.
function toUpper($pockets) {
return $pockets[1].strtoupper($pockets[2]).$pockets[3];
}
$str = 'Three captains, one ship.';
$str = preg_replace_callback('{(</?)(\w+)(.*?>)}s', "toUpper", $str);
echo htmlspecialchars($str);



Получение строки GET-запроса.


Для начала поставим самую простую задачу - получить часть URL, содержащую GET-параметры.


function ggp($url) { // get GET-parameters string
preg_match('/^(.+?)(\?.*?)?(#.*)?$/', $url, $matches);
$gp = (isset($matches[2])) ? $matches[2] : '';
return $gp;
}

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

Исключение GET-запроса из URL.


Иногда нужно получить URL без GET-параметров (например, при перенаправлении запросов
с помощью mod_rewrite зачастую требуется проводить анализ URL,
чтобы сформировать ответ клиенту;
нередко для анализа нужна только статическая часть URL,
а часть, где передается GET-запрос, не нужна и даже мешает).
// удаление GET-параметров из URL
$str = preg_replace('/^(.+?)(\?.*?)?(#.*)?$/', '$1$3', $url);


заменить все символы кроме чисел и запятой на ''


$value = preg_replace('/[^\d,]+/', '', $value); // заменить все символы кроме чисел и запятой на ''


Есть ли в строке параметров сессия (PHPSESSID):


print $_SERVER['REQUEST_URI'].'<br>';
if (preg_match("/=([a-f0-9]{32})&/i", $_SERVER['REQUEST_URI'].'&')){
print 'Да';
// удалить сессию из строки параметров
//print str_replace('&&','&',str_replace('?&','?',preg_replace("/&*sid=([a-f0-9]{32})&*/i", '&', $_SERVER['REQUEST_URI'])));
}
else print 'Нет';


Удалить из строки параметр page и добавить другой page.


Этот пример позволяет заменить один параметр на другой не испортив все остальные параметры строки.
Если Вы найдете более оптимальное решение, присылайте.
$href1=str_replace('&&','&',str_replace('?&','?',preg_replace("/&*page=([0-9]{1,3})&*/i", '&', $_SERVER['REQUEST_URI'])));
$href1=str_replace('?&','?',$href1.(strpos($href1, '?')===false?'?':'&').'page=');


Ссылка на ресурс

Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.