Форум АНТИЧАТ

Форум АНТИЧАТ (https://forum.antichat.xyz/index.php)
-   Авторские статьи (https://forum.antichat.xyz/forumdisplay.php?f=31)
-   -   Регулярные выражения [Beta-version] (https://forum.antichat.xyz/showthread.php?t=35938)

Talisman 20.03.2007 11:26

Регулярные выражения [Beta-version]
 
Привет, все же эта статья не о моих мыслях, а о созданном до меня творении - регулярных выраженийх, то не буду копипастить "заводские" мануалы, а сразу перейду к делу.
Регулярные выражения
Как всегда, материал для затравки:
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
PHP код:

int preg_match(
string pattern// регулярка
string subject// строка, где ищем
[, array matches// куда поместятся результаты поиска


Тамошний примерчик:
PHP код:

 <?
  
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/functio...-match-all.php -аналогична простому preg_match, только эта позволяет задать порядок, в котором выводятся результаты:
PHP код:

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 - разбивает строку в соответствии с регулярным выражением и возвращает массив строк, как функция split() ( http://ru2.php.net/manual/en/function.split.php ):
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 - обрабатывает стрчоку по шаблону, например:
PHP код:

$hash=ereg_replace("[^0-9a-fA-F]","",$hash); 

заменит все, что не цифра и не буква: abcdefABCDEF на пустое множество, т.е. вырежет все, кроме допустимых символов в хеше)
PHP - Иной взгляд
Вот другой взгляд на то же, про что и я говорил :)
http://www.providerz.ru/articles/php...-continue.html
Правила хорошего тона:
Комментируйте свои регулярки! ведь их наверняка нужно будет комментировать/изменять, поэтому совет:
PHP код:

$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
жду камментов)

Isis 20.03.2007 11:30

Статья не знаю зачем :) Плюс блин поставил)
Вот этого хватит вполне http://php.spb.ru/php/regexp.html

Talisman 20.03.2007 11:52

Элементарные действия

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

PHP код:

 if(ereg("^ // отрицание
[0-9] // цифры
{1,77} // квантификатор повтора предыдущего элемента (цифр) от 1 до 77 раз
$"
,$string)) echo "yes"; else echo "no"

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

 if (ereg("^ //отрицание
[a-zа-я0-9_] // цифры, буквы русские, англ (строчные), и подчеркивание
{5,20} // повторяются не менее 5 и не более 20 раз
$"
,$string)) echo "yes"; else echo "no"

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

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

Для регистро независимого сравнения используйте eregi().
Есть ли в строке идущие подряд символы, не менее 3-х символов подряд (типа "абвгДДДеё", но не "ааббаабб"):

PHP код:

if (preg_match("/(.)\\1\\1/",$string)) echo "yes"; else echo "no"

Заменить везде в тексте СТРОКУ1 на СТРОКУ2 (задача решается без регегулярных выражений):

PHP код:

$string=str_replace("СТРОКА1","СТРОКА2",$string); 

Заменить кривые коды перехода строки на нормальные: для этого нужно только удалить "\r". Переходы бывают нормальными (но разными!): "\n" или "\r\n". Еще бывают глюки, типа "\r\r\n".

PHP код:

$string=str_replace("\r","",$string); 

Заменить все повторяющиеся пробелы на один. Не пытайтесь здесь применить str_replace, это хорошая функция, но не для данного примера.

PHP код:

$string=preg_replace("/ХХ+/","Х",$string); // вместо Х поставьте пробел 

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

$string=preg_replace("/(слово1|слово2|ляляля|слово99)/si","<b>\\1</b>",$string);
// то, что в скобках, заносится потом в \\1
// вертикальная черта означает или :)
// остальное вроде все понятно 

Найти текст, заключенный в какой-то тег, например <TITLE> ... </TITLE> из HTML-файла ($string - исходный текст).

PHP код:

//точка - все кроме пробела, ну и много раз повторяется)
if (preg_match("!<title>(.*?)</title>!si",$string,$ok))
   echo 
"Тег найден, текст: $ok[1]";
else
   echo 
"Тег не найден"

Найти текст, заключенный в какой-то тег и заменить его на другой тег, например: <TITLE> ... </TITLE> заменить аналогично на <МОЙ_ТЕГ> ... </МОЙ_ТЕГ> в HTML-файле:
PHP код:

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


Abra 20.03.2007 12:06

Даж не знаю... помоему для азов - статья слишком простая. Имхо, лучше было бы написать статью про крутые регулярки, а не про элементарные. Что-то из серии ББ кодов с хорошими фильтрами, чтоб народ учился их сам писать. Ну или там с модификатором /e.

Еще не заметл жирную надпись в самом начале "для простого поиска/замены" используется strpos и str_replace а не регулярки!!!".=)) Многие, познав такую вещь как regexp начинают ей злоупотреблять почем зря =\

UPD только сейчас заметил: "можт все же перевести на ВВ-теги форума?" - думаю надо. Большинство людей для других целей их и не использует. А безопасность BBкодов + там фильтрация на вложенные 2ые, и 3ые тэги - вообще сама по себе интересная тема, если осилишь :)

Talisman 20.03.2007 12:08

ок, щас распознавалку бб кодов распишу подробно (самописка)
---добавлено---
Почемуто многие самописные сайты разрешают штмл в своей админке, уж не из-за того ли, что создателям "влом" писать распознавалку бб тегов?
вот простейший пример:
[php]<?

// исходное сообщение:
// ------------------------------------------------------
$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]
[HIDE]тут хайд))) токо что в нем написать?[/HIDE]
<?
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;
}

// ищем в тексте все куски между <?... или
PHP код:

...
$str=preg_replace("!(\[php\]|<\?)(.*?)(\[/php\]|\?>)!ise","_my_('\\2','\\1','\\3')",$str);
$order  = array('[center]','[/center]','[left]','[/left]','[right]','[/right]','[b]','[/b]');
$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;

?> 

тут мы использовали несколько красивых регулярок для наших бб тегов:
PHP код:

$str ereg_replace("\[HIDE\](.*)\[\/HIDE\]","<HR>\\1<HR>"$str); 

- заменяет текст, между [HIDE] и [/HIDE] на тот же текст, но в тегах <HR>, чтобы выделить его из общей массы. (конечно, нужно юзать ксс, чтобы было читабельнее))
PHP код:

 $str ereg_replace("\[URL\]([[:alpha:]]+://[^<>[:space:]]+[[:alnum:]/])\[\/URL\]","<a href=\"\\1\" target=\"blank\">\\1</a>"$str); 

а эта регулярка обрабатывает урл адрес. ЭТО ТОЛЬКО МОДЕЛЬ! нужно во-первых, текст, отображаемый пользователю разбивать на участки, во избежание XSS атак, да и фильтровать его :)
Заметьте, срабатывают эти регулярки, только если if($_GET['member']==='1') - истинно (так мы упростили систему авторизации), если же это ложно, то вместо хайдов выводится:
Код HTML:

<HR><b>Стань мембром! или не видать тебе хайдов и линков!!!</b><HR>
и вместо линков то же самое, сделано это чуть измененными регулярками:
PHP код:

      $str ereg_replace("\[HIDE\](.*)\[\/HIDE\]","<HR><b>Стань мембром! или не видать тебе хайдов и линков!!!</b><HR>"$str);
$str ereg_replace("\[URL\]([[:alpha:]]+://[^<>[:space:]]+[[:alnum:]/])\[\/URL\]","<b>Стань мембром! или не видать тебе хайдов и линков!!!</b>"$str); 

К тому же, мы и заменяем теги [center], [b] на аналогичные штмл вот таким кодом:
PHP код:

 $order  = array('[center]','[/center]','[left]','[/left]','[right]','[/right]','[b]','[/b]');
$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

Цитата:

Сообщение от Abra
Даж не знаю... помоему для азов - статья слишком простая. Имхо, лучше было бы написать статью про крутые регулярки, а не про элементарные. Что-то из серии ББ кодов с хорошими фильтрами, чтоб народ учился их сам писать. Ну или там с модификатором /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

Цитата:

Сообщение от mR_LiNK[deface_0nl
согласен, также основа - explode(); imdplode();
)вот те статья - продвинутые реги http://www.intuit.ru/department/pl/plphp/class/free/13/5.html

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

в конце статьи я и спросил про целесообразность :)

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

Talisman 20.03.2007 15:24

да, забыл, спасибо за линк)
тогда уж получится хорошая подборка линков на мануалы)

Abra 20.03.2007 16:32

Цитата:

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

Talisman я там один пост выше апдейтил, может ты не заметил. Не рискнешь сделать статью про безопасные ББ коды? Т.е. показать как делать ББкоды максимально устойчивые к КСС (с хорошей фильтрацией вложенных тегов). Это конечно труд непосильный, тут тебе действительно цены не будет. Я бы даже присоединился/присоединюсь к разработке, если в армию не заберут в ближайшие два месяца ))) Сам давно этим вопросом занимаюсь. Конечно всегда есть ризон выдернуть класс для обработки ббкодов из того же vbulletin'a, но все таки желание изобрести велосипед так и прет в этом вопросе =\\

ЗЫ целесообразность в вопросе регулярок есть всегда, главное правильно это дело представить. Эта статья (фактически ликбез) все таки немного не то. Как сделать "то", не спрашивай ))


Время: 21:26