Просмотр полной версии : Регулярные выражения [Beta-version]
Talisman
20.03.2007, 11:26
Привет, все же эта статья не о моих мыслях, а о созданном до меня творении - регулярных выраженийх, то не буду копипастить "заводские" мануалы, а сразу перейду к делу.
Регулярные выраженияКак всегда, материал для затравки:
http://molody.tagiltelecom.ru/doc/program/www/php4/ru/reference.pcre.pattern.syntax.html
и http://www.providerz.ru/articles/php/regexp-intro.html
прочитали? ну хотябы просмотрели? тогда едем дальше :)
PHP
Разберу только пшп, ибо наиболее распространен, да и в перле все точно так же)
Функции, которые работают с регулярками:
preg_match - http://ru2.php.net/manual/en/function.preg-match.php
int preg_match(
string pattern, // регулярка
string subject, // строка, где ищем
[, array matches] // куда поместятся результаты поиска
)Тамошний примерчик:
<?
function is_email($Addr)
{
$p = '/^[a-z0-9!#$%&*+-=?^_`{|}~]+(\.[a-z0-9!#$%&*+-=?^_`{|}~]+)*'; // имя аккаунта
$p.= '@([-a-z0-9]+\.)+([a-z]{2,3}'; // зоны второго уровня
$p.= '|info|arpa|aero|coop|name|museum)$/ix'; // зоны первого уровня
return preg_match($p, $Addr);
}
?>preg_match_all - http://ru2.php.net/manual/en/function.preg-match-all.php -аналогична простому preg_match, только эта позволяет задать порядок, в котором выводятся результаты:
int preg_match_all(
string pattern, // регулярка
string subject, // строка, где ищем
array matches // куда поместятся результаты поиска
[, int order] // порядок размещения строк в результирующем массиве, принимает значения:
PREG_PATERN_ORDER - нулевой элемент будет массивом полных соответствий шаблону.
PREG_SET_ORDER - начиная с нулевого симовола
)Как видно, эта функция просто более удобна в некоторых ситуациях.
preg_split -http://ru2.php.net/manual/en/function.preg-split.php (http://ru2.php.net/manual/en/function.preg-match-all.php) - разбивает строку в соответствии с регулярным выражением и возвращает массив строк, как функция split() ( http://ru2.php.net/manual/en/function.split.php ):
array preg_split(
string pattern, // регулярка
string subject, // строка, которую разбиваем
[, int limit // ограничение найденных значений
[, int flags] // если указать PREG_SPLIT_NO_EMPTY то функция вернет только не пустые строки
)ereg_replace - http://ru2.php.net/manual/en/function.ereg-replace.php - обрабатывает стрчоку по шаблону, например:
$hash=ereg_replace("[^0-9a-fA-F]","",$hash);заменит все, что не цифра и не буква: abcdefABCDEF на пустое множество, т.е. вырежет все, кроме допустимых символов в хеше)
PHP - Иной взгляд
Вот другой взгляд на то же, про что и я говорил :)
http://www.providerz.ru/articles/php/regexp-continue.html
Правила хорошего тона:
Комментируйте свои регулярки! ведь их наверняка нужно будет комментировать/изменять, поэтому совет:
$hash=ereg_replace("[^ // все кроме
0-9 // цифры
a-f // мелкие буквы abcdef
A-F // большие буквы на всяк случай ABCDEF
]","",$hash);
так понятнее, ведь правда?
Зачем?
фильтровать передаваемые скрипту значения, "сдирать" инфу с чужого сайта, да много еще как)
ЗЫ: не спешите баянить, если что-то не понравилось... ИБО: не решился сразу переводить те 2 начальные статьи, ибо зачем? а щас появились сомнения. можт все же перевести на ВВ-теги форума?
че сделать с теми статьями? "переварить", откомментировав каждые регулярки?
ибо много где регулярки используются, а из-за отстуствия простой документации много вещей непонятны :)
ЗЫ еще в тему: http://forum.antichat.ru/thread27498-%F0%E5%E3%F3%EB%FF%F0%ED%FB%E5.html
жду камментов)
Статья не знаю зачем :) Плюс блин поставил)
Вот этого хватит вполне http://php.spb.ru/php/regexp.html
Talisman
20.03.2007, 11:52
Элементарные действия
Является ли строка числом, длиной до 77 цифр:
if(ereg("^ // отрицание
[0-9] // цифры
{1,77} // квантификатор повтора предыдущего элемента (цифр) от 1 до 77 раз
$",$string)) echo "yes"; else echo "no"; Состоит ли строка только из букв, цифр и "_", длиной от 5 до 20 символов:
if (ereg("^ //отрицание
[a-zа-я0-9_] // цифры, буквы русские, англ (строчные), и подчеркивание
{5,20} // повторяются не менее 5 и не более 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); // вместо Х поставьте пробел В тексте есть некоторые слова, допустим "СЛОВО" и "ЛЯЛЯЛЯ" (и т.д.), которые нужно одинаковым образом заменить на тоже самое, но с добавками. Возможно, слова отсутствуют или встречаются много раз в любом регистре. Т.е. если было "слово" или "СлОвО" (или еще как), нужно заменить это на "<b>слово</b>" или "<b>СлОвО</b>" (смотря, как было). Другими словами нужно найти перечень слов в любом регистре и вставить по краям найленных слов фиксированные строки (на "<b>" и "</b>").
$string=preg_replace("/(слово1|слово2|ляляля|слово99 )/si","<b>\\1</b>",$string);
// то, что в скобках, заносится потом в \\1
// вертикальная черта означает или :)
// остальное вроде все понятно
Найти текст, заключенный в какой-то тег, например <TITLE> ... </TITLE> из HTML-файла ($string - исходный текст).
//точка - все кроме пробела, ну и много раз повторяется)
if (preg_match("!<title>(.*?)</title>!si",$string,$ok))
echo "Тег найден, текст: $ok[1]";
else
echo "Тег не найден";Найти текст, заключенный в какой-то тег и заменить его на другой тег, например: <TITLE> ... </TITLE> заменить аналогично на <МОЙ_ТЕГ> ... </МОЙ_ТЕГ> в HTML-файле:
preg_replace("!<title>(.*?)</title>!si","<МОЙ_ТЕГ>\\1</МОЙ_ТЕГ>",$string);
Даж не знаю... помоему для азов - статья слишком простая. Имхо, лучше было бы написать статью про крутые регулярки, а не про элементарные. Что-то из серии ББ кодов с хорошими фильтрами, чтоб народ учился их сам писать. Ну или там с модификатором /e.
Еще не заметл жирную надпись в самом начале "для простого поиска/замены" используется strpos и str_replace а не регулярки!!!".=)) Многие, познав такую вещь как regexp начинают ей злоупотреблять почем зря =\
UPD только сейчас заметил: "можт все же перевести на ВВ-теги форума?" - думаю надо. Большинство людей для других целей их и не использует. А безопасность BBкодов + там фильтрация на вложенные 2ые, и 3ые тэги - вообще сама по себе интересная тема, если осилишь :)
Talisman
20.03.2007, 12:08
ок, щас распознавалку бб кодов распишу подробно (самописка)
---добавлено---
Почемуто многие самописные сайты разрешают штмл в своей админке, уж не из-за того ли, что создателям "влом" писать распознавалку бб тегов?
вот простейший пример:
<?
// исходное сообщение:
// ------------------------------------------------------
$str='
Памагите, ничаво не работает! Вот пример:
[ph p ]
// comment
# comment
phpinfo();
[/ph p]
содран с: http://yandex.ru/
ляляля ляляля
ПОМОГИТЕ!!!
[ph p]
for ($i=0; $i<100; $i++) {
ping("-f","www.ru");
}
[/ph p]
тут хайд))) токо что в нем написать?
<?
echo "<a href=http://php.spb.ru/chat/>click here!</a>";
phpinfo();
?>
';
// ------------------------------------------------------
// подавить предупреждения (в highlight_string есть глюки)
error_reporting(0);
// функция подсвечивания одного куска текста
function _my_($s,$a1,$a2) {
if ($a1!="<?") { $a1="<?"; $a2="?>"; }
$s=str_replace("\\\"","\"",$s);
ob_start();
highlight_string($a1.$s.$a2);
$s=ob_get_contents();
ob_end_clean();
return $s;
}
// ищем в тексте все куски между <?... или ...
$str=preg_replace("!(\[php\]|<\?)(.*?)(\[/php\]|\?>)!ise","_my_('\\2','\\1','\\3')",$str);
$order = array('','','','','','','','');
$replace = array('<div align="center">','</div>','<div align="left">','</div>','<div align="right">','</div>','<B>','</B>');
$str = str_replace($order, $replace, $str);
// хайд )
if($_GET['member']==='1')
{
$str = ereg_replace("\[HIDE\](.*)\[\/HIDE\]","<HR>\\1<HR>", $str);
$str = ereg_replace("\[URL\]([[:alpha:]]+://[^<>[:space:]]+[[:alnum:]/])\[\/URL\]","<a href=\"\\1\" target=\"blank\">\\1</a>", $str);
}else
{
$str = ereg_replace("\[HIDE\](.*)\[\/HIDE\]","<HR><b>Стань мембром! или не видать тебе хайдов и линков!!!</b><HR>", $str);
$str = ereg_replace("\[URL\]([[:alpha:]]+://[^<>[:space:]]+[[:alnum:]/])\[\/URL\]","<b>Стань мембром! или не видать тебе хайдов и линков!!!</b>", $str);
}
echo $str;
?>тут мы использовали несколько красивых регулярок для наших бб тегов:
$str = ereg_replace("\[HIDE\](.*)\[\/HIDE\]","<HR>\\1<HR>", $str); - заменяет текст, между и на тот же текст, но в тегах <HR>, чтобы выделить его из общей массы. (конечно, нужно юзать ксс, чтобы было читабельнее))
$str = ereg_replace("\[URL\]([[:alpha:]]+://[^<>[:space:]]+[[:alnum:]/])\[\/URL\]","<a href=\"\\1\" target=\"blank\">\\1</a>", $str); а эта регулярка обрабатывает урл адрес. ЭТО ТОЛЬКО МОДЕЛЬ! нужно во-первых, текст, отображаемый пользователю разбивать на участки, во избежание XSS атак, да и фильтровать его :)
Заметьте, срабатывают эти регулярки, только если if($_GET['member']==='1') - истинно (так мы упростили систему авторизации), если же это ложно, то вместо хайдов выводится:
<HR><b>Стань мембром! или не видать тебе хайдов и линков!!!</b><HR>и вместо линков то же самое, сделано это чуть измененными регулярками:
$str = ereg_replace("\[HIDE\](.*)\[\/HIDE\]","<HR><b>Стань мембром! или не видать тебе хайдов и линков!!!</b><HR>", $str);
$str = ereg_replace("\[URL\]([[:alpha:]]+://[^<>[:space:]]+[[:alnum:]/])\[\/URL\]","<b>Стань мембром! или не видать тебе хайдов и линков!!!</b>", $str);К тому же, мы и заменяем теги , [b] на аналогичные штмл вот таким кодом:
[php] $order = array('[center]','','','','','','','');
$replace = array('<div align="center">','</div>','<div align="left">','</div>','<div align="right">','</div>','<B>','</B>');
$str = str_replace($order, $replace, $str);теперь о проблемах такой схемы. заметили, что я выложил пшп код не в тегах ?
а почему? дело в том, что вобла пользуется аналогичным алгоритмом, который я описал, ей наплевать на правильную "скобочную" последовательность! как например [p hp][p hp][/ph p][/ph p] такой код она сглотит как: [ph p][p hp][/p hp] и отдельно стоящий [/ph p]. плохо, правда? как же этого избежать? можно юзать правильно настроенные регулярки в отношении жадности, а можно пойти совсем другим алгоритмом, его я опишу лиш на словах, т.к. нормальную версию кодю уже недельку)
суть, мы разбиваем сообщение на "части" учитывая правильные скобочные последовательности, и работаем с ними функциями, например, в теге пшп запрещены теги [b] и т.д.
Но, почему же вбуллетин не использует это? да потому, что тогда полетит к черту вся система плагиноВ, точнее она не полетит, ее можно будет сделать, но уже только с помощью графов (более простого метода мне в голову пока не лезет :( ). а так каждый модуль, как например тег "оффтом" на аллчитс добавляет еще 1 регулярку.
Тема очень обширная, поэтому если есть вопросы, пишите)
да и от предложений тоже не откажусь))))
ЗЫ проблему с [php] решил, просто пробелов понавставлял)))
mR_LiNK[deface_0nl
20.03.2007, 15:21
Даж не знаю... помоему для азов - статья слишком простая. Имхо, лучше было бы написать статью про крутые регулярки, а не про элементарные. Что-то из серии ББ кодов с хорошими фильтрами, чтоб народ учился их сам писать. Ну или там с модификатором /e.
Еще не заметл жирную надпись в самом начале "для простого поиска/замены" используется strpos и str_replace а не регулярки!!!".=)) Многие, познав такую вещь как regexp начинают ей злоупотреблять почем зря =\
согласен, также основа - explode(); imdplode();
)вот те статья - продвинутые реги http://www.intuit.ru/department/pl/plphp/class/free/13/5.html(мало, но тонкость, что приятно /сумеешь обмозговать и передать простым языком и со смешанными примерами - цены тебе не будет))
имхо, не вижу смысла описывать реги, и писать целую статью на тему. Материала уйма, и не так сложно найти понятное изложение.. ну да ладно, теперь на вопры по регам буду ссылку давать..
зы: репу зарабатываешь))
Talisman
20.03.2007, 15:23
согласен, также основа - explode(); imdplode();
)вот те статья - продвинутые реги http://www.intuit.ru/department/pl/plphp/class/free/13/5.html
имхо, не вижу смысла описывать реги, и писать целую статью на тему. Материала уйма, и не так сложно найти понятное изложение.. ну да ладно теперь на вопры по регам буду ссылку давать..
зы: репу зарабатываешь))
в конце статьи я и спросил про целесообразность :)
про репу: есть более простые методы, чем про регулярки рассказывать) если хочешь, покажу )))
Talisman
20.03.2007, 15:24
да, забыл, спасибо за линк)
тогда уж получится хорошая подборка линков на мануалы)
про репу: есть более простые методы, чем про регулярки рассказывать) если хочешь, покажу )))
Угу, есть. Так что не думаю что автор за ней гоняется, имхо )
Talisman я там один пост выше апдейтил, может ты не заметил. Не рискнешь сделать статью про безопасные ББ коды? Т.е. показать как делать ББкоды максимально устойчивые к КСС (с хорошей фильтрацией вложенных тегов). Это конечно труд непосильный, тут тебе действительно цены не будет. Я бы даже присоединился/присоединюсь к разработке, если в армию не заберут в ближайшие два месяца ))) Сам давно этим вопросом занимаюсь. Конечно всегда есть ризон выдернуть класс для обработки ббкодов из того же vbulletin'a, но все таки желание изобрести велосипед так и прет в этом вопросе =\\
ЗЫ целесообразность в вопросе регулярок есть всегда, главное правильно это дело представить. Эта статья (фактически ликбез) все таки немного не то. Как сделать "то", не спрашивай ))
vBulletin® v3.8.14, Copyright ©2000-2026, vBulletin Solutions, Inc. Перевод: zCarot