Жадность в регулярных выражениях

Роберт

Аналитик
Жадность в регулярных выражениях

Народ , подскажите как в PHP сделать НЕ жадный запрос в регулярных выражениях?
С самими регулярными выражениями работаю уже года 4 но восновном в Делфи и UNIX'овскими GREP'ами , а тут в PHP залез и смотрю что они не совместимы :(
Вот собственно простинькое регулярное выражение:
[?&](ee=(.+?)&)
Тоесть фрагмент начинается со знака ? или знака & , потом идёт ee= , и далее до БЛИЖАЙШЕГО знака &.
Проблема именно с тем чтобы "до ближайшего". Он ругается фразой:
Warning: REG_BADRPT:
что расшифровывается как
--
(неправильное использование операторов повторения,
таких, как `*', в качестве первых символов);
--
По крайней мере так написано в документации по linux'у.
Если вместо (.+?) пишу простой жадный запрос (.+) тогда всё работает , но ясное дело не до ближайшего , а до последнего знака &.

Помогите если кто знает?
Знаю что в PHP можно использовать перловские запросы но не знаю пойдётли это дело на виндовсе. Может кто может написать как этоже будет выглядеть в PERL'овском запросе под PHP?
 

si

Administrator
используй по возножности preg_* функции это Perl-compatible
Они на порядок быстрее чем POSIX и к тому же они мощнее и есть в них +?
 

Роберт

Аналитик
А как этот запрос будет выглядеть под preg_ ?
Там ведь чуток другой синтаксис , какие-то вначале и в конце слэши с мусором добавляются (если я не ошибаюсь).

А вот по поводу того , что он быстрее - я бы не стал утверждать! Тут один очень интересный мануал читал по поводу оптимизации работы в PHP , интересную вещь пишут - preg_ действительно на 50% - 500% быстрее ereg'a но это в случае если результат будет найден. А в случае если то , что ты ищешь не присутствует в строке , то preg_овский запрос от 10 до 100 РАЗ медленне работает чем ereg!!!
Судя по тому как написан был мануал я сомневаюсь что там врут.
Вобщем сейчас поищу его и выложу сюда , пусть кому интересно потестирует...
 

fisher

накатила суть
Originally posted by Роберт
А как этот запрос будет выглядеть под preg_ ?
ну, например

PHP:
$dummy = 'что несете?ee=самовар&сколько&стоит?ee=3 рубля&';
$format = '/[?&](ee=(.+?)&)/';
$matches = array();
preg_match_all ($format,$dummy,$matches) ? 
    var_dump($matches) : print "preg_match failed.";
дамп:
array(3) {
[0]=>
array(2) {
[0]=>
string(12) "?ee=самовар&"
[1]=>
string(12) "?ee=3 рубля&"
}
[1]=>
array(2) {
[0]=>
string(11) "ee=самовар&"
[1]=>
string(11) "ee=3 рубля&"
}
[2]=>
array(2) {
[0]=>
string(7) "самовар"
[1]=>
string(7) "3 рубля"
}
}

по ключам дампа: [0]что попало, [1]внешние скобки, [2]внутренние скобки. порядок там можно менять, RTFM
 

si

Administrator
Возножно Вы и умный мануал читали, но мой опыт говорит что перловые быстрее гораздо, приведите плиз пример обратного.

Только не сочинения очередного автора, и просто пример выражения. Некоторые выражения способны завесить движек regexp, такие примеры не принимаються, т.к это ошибочные выражения, а не проблема regexp engine.
 

Роберт

Аналитик
Автор оригинала: si
Только не сочинения очередного автора...
Вот , нашол его. Я всётаки дам сюда ссылку (помоему статья интересная , хотя я никогда ею не руководствовался ВОТ ОНА
А пример прост:
Есть текстовый файл размером 28Мб , в котором нет НИ ОДНОГО Е-Майловского адреса (тоесть нет символа "@") , и два варианта поиска (PHP и Перловский)
  1. {eregi("([a-z_-]+@([a-z][a-z-]*\.)+([a-z]{2}|com|mil|org|net|gov|edu|arpa|info|biz))",$text,$ok); echo $ok[1];}
  2. {preg_match("/([a-z_-]+@([a-z][a-z-]*\.)+([a-z]{2}|com|mil|org|net|gov|edu|arpa|info|biz))/im",$text,$ok); echo $ok[1];}
    [/list=1]

    Первый вариант отрабатывает за 0.5 секунды , второй за 5 секунд...
    Или ты не согласен?
 

si

Administrator
Пару примеров :
файл 34M

/m - я убрал из перлового, т.к он там не нужен (зачем его туда поставили, надо у авторы спросить)

PHP:
  eregi("([a-z_-]+@([a-z][a-z-]*\.)+([a-z]{2}|com|mil|org|net|gov|edu|arpa|info|biz))",$text,$ok);

  if (strpos($text,'@')!==false)
    preg_match("/([a-z_-]+@([a-z][a-z-]*\.)+(com|mil|org|net|gov|edu|arpa|info|biz|[a-z]{2}))/i",$text,$ok);
@ нет:
Time: 0.66456198692322 sec
Time: 0.36017000675201 sec

'@' есть (в конце файла):
Time: 141.86080098152 sec
Time: 17.437381982803 sec

'@' есть (в начале файла):
Time: 0.72716689109802 sec
Time: 0.014925003051758 sec

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

Роберт

Аналитик
Често скажу , сам до этого не тестировал , но раз уж ты прислал результаты , я не смог остаться равнодушним и сам полез тестировать. Полученные мной результаты полностью (пропорционально) совпадают с тем , что написал автор.
Не будем сейчас рассмотривать тот вариант когда @ есть. Тут ясно что перловская будет выигрывать.
Но не всегда ты уверен , что от регулярное выражение получит результат (это как if , может получишь then , а может else).
Ты решил отделаться от этого простой проверкой всего текста на наличие знака @. Видя что у тебя статус Администратора я конечно понимаю , что могу вылетить из форума , но всётаки смею утвержать что такая проверка - это ЧИСТО ПО ДЕТСКИ!
Ты что перед кадым запросом сейчас собираешься его проверить на наличие каких-то составляющих? А если тебе надо найти не Е-Майл , а допустим Почтовый индекс или Телефонный номер. На что ты тогода будешь проверять чтобы доказать что перловская функция не уступает?
 

fisher

накатила суть
Originally posted by Роберт
смею утвержать что такая проверка - это ЧИСТО ПО ДЕТСКИ!
ты выбирай - шашечки или ехать... или мнимую "красоту", или второй вариант,если уж тебе так важна производительность.

P.S. денормализация теоретически тоже вроде как по-детски, а при грамотной реализации жизнь облегчает - огого.
 

Роберт

Аналитик
Автор оригинала: fisher
P.S. денормализация теоретически тоже вроде как по-детски...
Ты не понял. Тут ведь не ведут речь о том , как сделать быстрой какуюто часть программы , тут просто преведён факт того , что перловские регулярные выражения не всегда быстрее пхп'эшных. Никто не сказал что какой-то вариант лучьше , просто мифы о том что preg_* всегда быстрее всех - должен быть развеян...
Чтобы тот кто будет что-то писать - осмыслилбы всё и выбралбы ЛУЧШУЮ функцию для своей конкретной задачи.
 

si

Administrator
Видимо вы меня не поняли или не захотели понять:

Во-первых идея была такова, что не надо всюду пихать regexp где надо и где не надо. Я согласен, что есть ситуации где перл-компатибле выражения медленней, но так-же есть способы, сделать так что-бы этих ситуаций стало меньше, в этом случае они буду давать существенноы выигрышь.

Во-вторых, пример со строкой в 34М не самый жизненный, логичнее обрабатывать такой файл по строкам.

В-третих: РНР вообще не предназначен для обработки таких файлов. У меня например версия mod_php просто падает на таком тексте.

1. В большенстве реальных ситуациях preg_* быстрее ereg_*
2. preg_* на много можнее ereg_*
3. Надо знать и понимать как работаею regexp чтобы их правильно писать

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

Видя что у тебя статус Администратора я конечно понимаю, что могу вылетить из форума
А разве вы дали повод для этого ? Я не заметил. Не судите о людях по себе.
 

fisher

накатила суть
Originally posted by Роберт
Чтобы тот кто будет что-то писать - осмыслилбы всё и выбралбы ЛУЧШУЮ функцию для своей конкретной задачи.
тред ты начал с того, что попросил написать тебе регулярное выражение, которое ты обломался написать ereg'ами. его тебе написали и посоветовали пользоваться прегами. преги тебе по каким-то загадочным причинам не нравятся, и ты привел 1 (один!) случай, когда preg медленнее. тебе привели код, который _всегда_ работает _гораздо_ быстрее. валяй, осмысливай :)

про объем файла - я с si полностью согласен, редкий изврат сразу в память такой объем.
 

Роберт

Аналитик
Автор оригинала: fisher
тред ты начал с того, что...
Какая разница с чего начал. С регулярными выражениями я работаю даааавно , и был удивлён , что ereg работает не по стандарту , а всё что я попросил это показать что там за слэши дополнительно ставятся в preg , так как в стандарном русском мануале от третьей версии про него preg ни строчки (и не надо сразу наезжать что мануалы читаются только на английском , а последняя версия 4.2)
И чего ты привязался к тому что si проверяет через if наличие знака "@"? Это пример который был в статье , которую я процитировал. Ну там для наглядности и показали что всё дело в этом знаке. А если мне надо телефонный номер найти? Ну , попробуй что-нибудь через if придумать!
И не надо говорит про 34Мб , я лично сразу тестировал при размере в 400Кб , и тоже самое! А задачи бывают разные...
 

si

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


что ereg работает не по стандарту ,
А давно не жадность это стандарт, в регах вообще нет никаких стандартов, все делают как им нравиться.

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

Роберт

Аналитик
Автор оригинала: si
Не заметно, что в этой проблеме есть решение без нежадноко +, что в другом вашем топике их несколько.
Не совсем понял что тут написано. Что-то ставится под сомнения?

А давно не жадность это стандарт, в регах вообще нет никаких стандартов, все делают как им нравиться.
Сколько в юниксах работаю , да и в делфи есть мощьная библиотека , ни разу не видел ни одного различия.
А ты можешь ещё привести хоть один пример где хоть в какойнибудь реализации отсутствовалабы нежадность?
 

si

Administrator
Не совсем понял что тут написано. Что-то ставится под сомнения?
То что вы НЕ давно с ними работаете или не знаите их.

Сколько в юниксах работаю , да и в делфи есть мощьная библиотека , ни разу не видел ни одного различия.
А ты можешь ещё привести хоть один пример где хоть в какойнибудь реализации отсутствовалабы нежадность?
В каких програмах на *nix есть не жадные +,* ? Бегло взглянул на sed там их нет.

Наверно единственный стандарт это POSIX, большинство других реалиций имеют свои стандарты,правила и особенности.
 

Роберт

Аналитик
Автор оригинала: si
То что вы НЕ давно с ними работаете или не знаите их.
Ты конкретно скажи что на это намекает?
Или может наличие в этомже форуме вопроса по поводу \\1число\\2??? В делфи $1число$2 работает отлично, а в PHP нет, но это проблема PHP, а не незнание регулярных выражений...

В каких програмах на *nix есть не жадные +,* ? Бегло взглянул на sed там их нет.
На будущее , чтоб ты знал , не плюс или звёздычка , а вопросительный знак свидетельствует о том , что выражение не жадное! А других учить пытаешься...

А по поводу того где они в юниксах - egrep посмотри , а то всякие примитивные фильтры сморишь.
 

tony2001

TeaM PHPClub
Роберт, не хами!
Тебе пытались очень вежливо и доходчиво объяснить свою точку зрения, а ты ведешь себя как последний 13-тилетний пацан.
 

si

Administrator
На будущее , чтоб ты знал , не плюс или звёздычка , а вопросительный знак свидетельствует о том , что выражение не жадное! А других учить пытаешься...
Я это знаю, вы читать научитесь или вам надо было написать. "В каких програмах на *nix есть не жадные квантификаторы". Нет никаой разницы как они будут обозначаться, вот придумали их в перле как +? и *?, но это не значит что так должно быть везде.

Или может наличие в этомже форуме вопроса по поводу \\1число\\2??? В делфи $1число$2 работает отлично, а в PHP нет, но это проблема PHP, а не незнание регулярных выражений...
Это не проблема РНР вовсе, это особенность реализации, причем это не реализация РНР а стороних библиотек. Вы просто не знаете как записать это выражение в этой реализации. А в дельфи возможно использовать >9 т.е $10, $11 и т.д ?

А по поводу того где они в юниксах - egrep посмотри , а то всякие примитивные фильтры сморишь.
Можно пример, и желательно цитату из мануала j нежадном варианте + или *. Я например не представляю как это можно проверить, т.к egrep просто говорит есть ли совпадение или нет, но не где оно было. Да и не нужна нежадность egrep т.к ему надо знать только о наличии совпадения.

Прекратите тупо спорить, о подумайте головой.

Еще раз: обе ваши проблемы имеют решения. Достаточно простые, может вы свои познания покажете на примере решения своих же задач ?
 

fisher

накатила суть
Автор оригинала: Роберт
На будущее , чтоб ты знал , не плюс или звёздычка , а вопросительный знак свидетельствует о том , что выражение не жадное!
охохох... Роберт, ну естественно имелся ввиду "нежадный +" и "нежадная *", "звёздычка" как ты изволил выразиться, то есть +? и *?, если тебе так будет понятно ...
посмотрев в твой второй топик, я пришёл к выводу, что тебе следует умерить пыл, и просто аккуратно, подробно написать, какую именно задачу ты собираешься решить. у меня есть сомнения, что ты выбрал верный подход. и пожалуйста, ни в коем случае не хами, если хочешь, чтоб тебе ответили.
 
Сверху