Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В. Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В. Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум Регулярные Выражения

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: наткнулся на регулярку
 
 автор: f111   (21.07.2011 в 01:28)   письмо автору
 
 

наткнулся на задачку на некотором сайте (если интересует могу разместить ссылку), задание звучит так: дана строка с переменным количеством символов. В ней могут встречаться символы: "a","b","/" в произвольном порядке. Нужно проверить, чтобы перед "b" было ноль или четное количество слешей.

через некоторое время на неё ответили, предложив в качестве ответа:
"{^ (?: [^/]++ | (?:/)++[^b] | (?://)*+ (?:b) )* $}x"

это выражение на мой взгляд идеально определят требуемые строки
/ba
b/a
a/b
/ab
ab/
//ab

//a/b
//bba
/a//bb

///b


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

буду премного благодарен объяснениям, а особенно подробным)

  Ответить  
 
 автор: SHAman   (21.07.2011 в 10:20)   письмо автору
 
   для: f111   (21.07.2011 в 01:28)
 

Хехе:) Это вы спрашивали на счет этого поста? Тесен мир)

Я дополнил его, кстати. Мне больше всего нравится мое решение. Оно, мне кажется, наиболее простое и логичное.

(?:b|a|^)(?:\/\/)*\/b


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

  Ответить  
 
 автор: f111   (21.07.2011 в 11:06)   письмо автору
 
   для: SHAman   (21.07.2011 в 10:20)
 

тот пост 2007 года, так что ничего удивительного)), а ваше решение (?:b|a|^)(?:\/\/)*\/b хоть и более простое и логичное, но не работает так как требуется...к сожалению(

у автора и хотел спросить, первым делом об этом подумал, но данных он своих не оставил

  Ответить  
 
 автор: SHAman   (21.07.2011 в 11:07)   письмо автору
 
   для: f111   (21.07.2011 в 11:06)
 

А комментарии на что?

Почему не работает? На какой строке не срабатывает?

  Ответить  
 
 автор: f111   (21.07.2011 в 11:46)   письмо автору
 
   для: SHAman   (21.07.2011 в 11:07)
 

прошу прощение, упустил из вида ваше сообщение.

вот тут проверьте http://gskinner.com/RegExr/ на этом наборе строк
/ba
b/a
a/b
/ab
ab/
//ab
//a/b
//bba
/a//bb
///b

и вы увидите как ведёт себя регулярка

  Ответить  
 
 автор: SHAman   (21.07.2011 в 15:04)   письмо автору
 
   для: f111   (21.07.2011 в 11:46)
 

Не доверяю я этим сервисам:) По-моему, проще скрипт наваять на коленке.

  Ответить  
 
 автор: SHAman   (21.07.2011 в 10:26)   письмо автору
 
   для: f111   (21.07.2011 в 01:28)
 

Поигрался. Во-первых, вторые плюсы можно смело удалять. Они ничего не делают, кажется.

Во-вторых, регулярка несколько избыточна. Вот моя версия.

{^ (?: [^/]+ | (?:/)+[^b] | (?://)*b)* $}x


Она описывает три варианта событий, которые могут повторяться. Варианты разделены |

Первый вариант - не / 1 или более раз. Это разрешенная конструкция. То есть, и a и b могут повторяться 1 и более раз.

Второй вариант - слэш 1 и более раз, а за ним не b. Вообще-то, можно вместо [^b] указать a, так как у нас маленькое множество. То есть, (?:/)+[^b] можно смело заменить на (?:/)+a.

Третий вариант - двойной слеш 0 и более раз (то есть, четное их количество), а за ним - b.

Любой из этих вариантов и любая их комбинация повторяется 0 и более раз. Это дает последняя * перед $.

  Ответить  
 
 автор: f111   (21.07.2011 в 11:08)   письмо автору
 
   для: SHAman   (21.07.2011 в 10:26)
 

{^ (?: [^/]+ | (?:/)+[^b] | (?://)*b)* $}x

уже лучше, но пропускает ///b

регулярка из того поста не пропускает даже ///////////////b(15 слэшей)

если в вашей регулярке добавить ещё один "плюс" - ^ (?: [^/]+ | (?:/)++[^b] | (?://)*b)* $
то и она не пропускает нечётное кол-во слэшей, так что видимо в них всё же есть глубокий смысл

  Ответить  
 
 автор: SHAman   (21.07.2011 в 11:34)   письмо автору
 
   для: f111   (21.07.2011 в 11:08)
 

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

  Ответить  
 
 автор: f111   (21.07.2011 в 11:40)   письмо автору
 
   для: SHAman   (21.07.2011 в 11:34)
 

>Количество слешей не имеет значения в данном случае.

ну я так, ради эксперимента

>В интернете ничего не нахожу по этому поводу.

а вы думали я просто так тему создал?)

  Ответить  
 
 автор: f111   (21.07.2011 в 13:10)   письмо автору
 
   для: SHAman   (21.07.2011 в 11:34)
 

всё никак логику не мог понять, даже после ваших объяснений, в ступоре сидел из-за первого условия [^/]+, казалось оно мне ненужным, лишним, и "так то" нашёл я вариант при котором оно не нужно
вуаля: {^ (?: /++[^b] | (?://)* [ba] )* $}x дальше как мне кажется уже сокращать некуда.
и снова без двойного квантификатоа никуда((, вот бы ещё смысл его применения понять

  Ответить  
 
 автор: f111   (21.07.2011 в 13:16)   письмо автору
 
   для: f111   (21.07.2011 в 13:10)
 

мля, только на этом сайте работает http://gskinner.com/RegExr/
в скрипте
$str = "/ba
b/a
a/b
/ab
ab/
//ab
//a/b
//bba
/a//bb
///b
//
///
ab
bb
aa";

$arr=explode("\n",$str);
for($i=0,$c=sizeof($arr);$i<$c;$i++){

if (preg_match('{^ (?: /++[^b] | (?://)* [ba] )* $}x', $arr[$i]))
echo ' is correct';
else
echo ' is incorrect';
echo '=> ',$arr[$i],'<br>';
}

не хочет, зря ликовал(

  Ответить  
 
 автор: Phantom   (20.08.2011 в 16:40)   письмо автору
 
   для: f111   (21.07.2011 в 13:10)
 

Вводим в гугл "Регулярные выражения", первая ссылка ведёт на википедию, нажимаем на неё, читаем всю страницу от начала и до конца. Несколько раз.
Ревнивая квантификация (Сверхжадная)

  Ответить  
 
 автор: f111   (20.08.2011 в 17:46)   письмо автору
 
   для: Phantom   (20.08.2011 в 16:40)
 

прочёл, но не доходит(((

ещё на одном ресурсе нашёл описание как:

*+ – захватывающие ноль или больше последовательных совпадений
++ – захватывающие одно или больше последовательных совпадений

но тоже не помогло вникнуть.

  Ответить  
 
 автор: f111   (21.08.2011 в 02:02)   письмо автору
 
   для: f111   (20.08.2011 в 17:46)
 

примеров "нормальных" нигде нет

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования