URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 9175
[ Назад ]

Исходное сообщение
"perl: затык с регэкспом"

Отправлено reekoff , 30-Июн-11 00:26 
Привет всем!
Вроде бы простой регэксп... но результат расходится с моими ожиданиями.
Первый вариант (работает как и ожидается):

    #!/usr/bin/perl
    $_ = 'qwerty';
    if ($_ =~ /   (([^e]|t)*)    /x) { print "$1\n" };


Здесь совпадет первая альтернатива в позиции строки до "e" , то бишь, в $1 - qw. До второй дело не доходит.

А здесь затык (t меняю на e):

    #!/usr/bin/perl
    $_ = 'qwerty';
    if ($_ =~ /   (([^e]|e)*)    /x) { print "$1\n" };


Я ожидаю, что совпадет первая альтернатива в позиции строки до "e", как и в первом случае.
Но совпадает вся строка - в $1 имеем qwerty.

Может я затупил конкретно или не понимаю сути... в общем, не могу разобраться в поведении этого выражения.
Разъясните, что к чему, если не сложно...


Содержание

Сообщения в этом обсуждении
"perl: затык с регэкспом"
Отправлено gibbon , 30-Июн-11 02:46 
>[оверквотинг удален]
>     #!/usr/bin/perl
>     $_ = 'qwerty';
>     if ($_ =~ /   (([^e]|e)*)  
>   /x) { print "$1\n" };
> Я ожидаю, что совпадет первая альтернатива в позиции строки до "e", как
> и в первом случае.
> Но совпадает вся строка - в $1 имеем qwerty.
> Может я затупил конкретно или не понимаю сути... в общем, не могу
> разобраться в поведении этого выражения.
> Разъясните, что к чему, если не сложно...

Как-то у вас все запутною Зачем писать такие регэкспы?

А работают они так как и должны.
Первый вариант.
Здесь вы в сущности ищите подстроку состоящую из не 'e' или из 't'.
Регэксп просматривает вашу строку qwerty слева направо.
Итак, первая буква 'q' это не 'e', она попадает в группу и продолжается просмотр.
Вторя буква 'w', это тоже не 'e' и она попадает в группу и продолжается просмотр.
Третья буква 'e', под условие не 'e' она не попадает, не попадает она и под альтернативную 't', так что на этом просмотр заканчивается и в группе итого 'qw'.
Регэксп ищет первое совпадение с шаблоном и на этом останавливается.

Второй вариант.
Здесь в регэкспе ([^e]|e) это все что не 'e' или 'e'. В сущности под это попадают все символы. Можно было записать там просто точку.
Регэксп просматривает все символы строку 'qwerty' и они все подходят под ваше условие. В итоге в группе оказывается вся строка 'qwerty'.


"perl: затык с регэкспом"
Отправлено cryo , 30-Июн-11 04:09 
Давайте зайдем с другой стороны. Опишите задание, что именно должен делать нужный вам регэксп?

"perl: затык с регэкспом"
Отправлено Pahanivo , 30-Июн-11 07:12 
([^e]|e)
что курил афтар ))))
пысы gibbon все правильно разжевал

"perl: затык с регэкспом"
Отправлено reekoff , 30-Июн-11 10:05 
> ([^e]|e)
> что курил афтар ))))
> пысы gibbon все правильно разжевал

Парни, спокойно!
Это просто теория.
В общем, есть гораздо более сложный регэксп, который я упростил для наглядности (выглядит аляповато, конечно) и привел здесь.

>    $_ = 'qwerty';
>    if ($_ =~ /   (([^e]|e)*)    /x) { print "$1\n" };
>Здесь в регэкспе ([^e]|e) это все что не 'e' или 'e'. В сущности под это попадают все символы.

Вот эту сущность можно разжевать?
Я думал, что если первая альтернатива имеет неуспех, то осущетсвляется переход на вторую, которая проверяется от сохраненного в начале строки состояния. Здесь, первая альтернатива хочет совпасть со всем кроме "e" как можно дальше (из-за *). И это ей удается поймав "qw".
Видимо, неверный ход мыслей. ))
Распишите, пожалуйста, посимвольно ход поиска. Не понятно, когда какая альтернатива работает.
Спасибо!


"perl: затык с регэкспом"
Отправлено cryo , 30-Июн-11 12:06 
цитата gibbon:
> Здесь в регэкспе ([^e]|e) это все что не 'e' или 'e'. В сущности под это попадают все символы.
> Можно было записать там просто точку.

Какое слово тут перевести? Эта альтернатива применяется для каждого символа. Т.к. альтернатива ничтожна (= .), то и в этот регэкс попадет _любая_ строка _любой_ длины _любых_ символов.


"perl: затык с регэкспом"
Отправлено reekoff , 30-Июн-11 12:17 
> цитата gibbon:
>> Здесь в регэкспе ([^e]|e) это все что не 'e' или 'e'. В сущности под это попадают все символы.
>> Можно было записать там просто точку.
> Какое слово тут перевести? Эта альтернатива применяется для каждого символа. Т.к. альтернатива
> ничтожна (= .), то и в этот регэкс попадет _любая_ строка
> _любой_ длины _любых_ символов.

Да не надо ничего переводить!
Попросил расписать ход поиска посимвольно. Не могу разобраться как работают эти 2 альтернативы, Ведь вторая совпадает только с символом "e" (сколько угодно раз)???


"perl: затык с регэкспом"
Отправлено ACCA , 30-Июн-11 16:58 
> Попросил расписать ход поиска посимвольно. Не могу разобраться как работают эти 2
> альтернативы, Ведь вторая совпадает только с символом "e" (сколько угодно раз)???

На сегодня брось эту проблему, вечером не пей. Завтра утром перечитай всю ветку, сразу поймёшь.

Вторая совпадает не только с символом "е". Ты сам просил, чтобы совпадало с "е" или не-"е".


"perl: затык с регэкспом"
Отправлено reekoff , 30-Июн-11 17:41 
>> Попросил расписать ход поиска посимвольно. Не могу разобраться как работают эти 2
>> альтернативы, Ведь вторая совпадает только с символом "e" (сколько угодно раз)???
> На сегодня брось эту проблему, вечером не пей. Завтра утром перечитай всю
> ветку, сразу поймёшь.
> Вторая совпадает не только с символом "е". Ты сам просил, чтобы совпадало
> с "е" или не-"е".

Нет, ну все же! :))

выражение:
"qwerty" =~ /(([^e]|e)*)/;
print "$1\n";
Имеем строку и регэксп с двумя альтернативами для поиска - [^e]* и e*, суть - ([^e]|e)*.
Поиск начинается с подшаблона заданного левой альтернативой и при неудаче переходит на правую. При неудаче правой альтернативы управление опять переходит на левую, но в позицию строки за которой закончился предыдущий поиск этой альтернативы. Так как скобки захватывают все выражение, в $1 пишется все. Так я понимаю?
Итак,
'не e' совпадает с q, далее по * 'не e' совпадает с w, далее 'не e' не совпадает с e (временная неудача поиска) и переход на вторую альтернативу в начало строки - 'e' не совпадает с q (временная неудача) - переход на первую альернативу в позицию за e, так как qwe уже обработано. Далее совпадение до конца строки.
Я гоню? А то, что-то больше у меня никак не получается...


"perl: затык с регэкспом"
Отправлено gibbon , 30-Июн-11 23:46 
>[оверквотинг удален]
> как скобки захватывают все выражение, в $1 пишется все. Так я
> понимаю?
> Итак,
>  'не e' совпадает с q, далее по * 'не e' совпадает
> с w, далее 'не e' не совпадает с e (временная неудача
> поиска) и переход на вторую альтернативу в начало строки - 'e'
> не совпадает с q (временная неудача) - переход на первую альернативу
> в позицию за e, так как qwe уже обработано. Далее совпадение
> до конца строки.
> Я гоню? А то, что-то больше у меня никак не получается...

Думаю вы не понимаете что ([^e]*|e*) != ([^e]|e)*.


"perl: затык с регэкспом"
Отправлено reekoff , 01-Июл-11 03:01 
> Думаю вы не понимаете что ([^e]*|e*) != ([^e]|e)*.

Очень рад, что общими усилиями нашли где у меня таки затык.
Теперь я понимаю, что, по-вашему, я не понимаю, что одно не равно другому.
Но ведь я и обратился на форум за пониманием. Можно пояснение?
Ведь мы имеем 2 альтернативы, и скобки задают действие квантификатора как для одной, так и для другой. Это, если, академично. Можно разжевать, где я не прав?
ps. Кстати,gibbon, мне понравилось разжевывание первого варианта кода:
>Первый вариант.
>Здесь вы в сущности ищите подстроку состоящую из не 'e' или из 't'.
>Регэксп просматривает вашу строку qwerty слева направо.
>Итак, первая буква 'q' это не 'e'...

Но там, и так, все ясно было...

а вот со вторым:
>Второй вариант.
>Здесь в регэкспе ([^e]|e) это все что не 'e' или 'e'. В сущности под это попадают все >символы...

получилась некая недосказанность, ага...


"ОМФГ...."
Отправлено Andrey Mitrofanov , 01-Июл-11 09:37 
>скобки задают действие квантификатора как для одной, так и для другой. Это, если, академично.

Студент, блин, ты не выпендривайся, ты пальцем покажи. :/

Если по человечи сказать, чего нужно "нарегэкспить", так хоть пример покажи.

Например, вот, мол, на входе "querty", на выходе хочу "que", но не могу.
Тебе добрые дяди скажут, что вместо своих эквивалентов .* надо взять ^[^e]*e*

$ echo querty | egrep -o ^[^e]*e*
que
$ _

> получилась некая недосказанность, ага...


"ОМФГ...."
Отправлено Pahanivo , 04-Июл-11 08:01 
людям несведующим с первого взгляда может показаться что регекспы - это как два пальца об асфальт ...
спешу вас заверить что это не так - это своя глубокая тема, чтобы ее понять надо почитать теорию из какой нибудь хорошей книжки типа "регулярные выражения" - в принципе ничего сложного нет, надо просто знать матчасть. пока термины типа "метасимволы", "жадность квантификаторов" и тд для вас непонятны - разговаривать с вами безсмысленно

"perl: затык с регэкспом"
Отправлено reekoff , 01-Июл-11 18:07 
> Может я затупил конкретно или не понимаю сути... в общем, не могу
> разобраться в поведении этого выражения.
> Разъясните, что к чему, если не сложно...

Все, разобрался.
ACCA, хоть я и пил пиво до 3-х утра, но сегодня озарило.
Действительно, затупил я. :))
Слишком сложно подошел к вопросу и ушел сразу не в ту степь - все оказалось гораздо проще.

'не e' совпадает с q - захват - переходим на второй символ строки;
'не e' совпадает с w - захват - переходим на третий;
'не e' не совпадает с e - нет захвата, но не беда - есть вторая альтернатива, на которую и переходит поиск -'e' совпадает с e - захват - переход на 4-й и первую альтернативу
'не e' совпадает с r, переход на t и так далее...
Вот примерно такой помощи ожидал...

ps. Изиняюсь, если заставил кого-то нервничать... Рад, что рассмешил кого-то...