Комментарии 22
Отличное дополнение к первой статье :).
Спасибо.
Спасибо.
Хм, я думал что неплохо разбираюсь в PCRE, но вот про «сверхжадные квантификаторы» не знал.
Спасибо за труд
Спасибо за труд
На здоровье :)
Если будет спрос, следующую заметку напишу про «бесконечный» бэктрекинг (откат), т. е. ситуацию, когда откат приводит к проверке миллионов вариантов и регекс кажется «зациклившимся», и то, как откат предотвратить (атомарную группировку). Собственно, сверхжадные квантификаторы — это частный случай атомарной группировки.
Если будет спрос, следующую заметку напишу про «бесконечный» бэктрекинг (откат), т. е. ситуацию, когда откат приводит к проверке миллионов вариантов и регекс кажется «зациклившимся», и то, как откат предотвратить (атомарную группировку). Собственно, сверхжадные квантификаторы — это частный случай атомарной группировки.
Присоеденяюсь!
Давно регспы юзаю и очень уважаю за их лакончиность, но вот про сверх-жадность не знал.
Огромное спасибо за интересный материал!
Давно регспы юзаю и очень уважаю за их лакончиность, но вот про сверх-жадность не знал.
Огромное спасибо за интересный материал!
Их ещё называют как "ревнивые квантификаторы". Потому что они не используют возвраты (backtracking). Не все движки регулярных выражений поддерживают их. Вместо них используют атомарные группы - atomic group. Это не ссылочные группы, которые забирают позиции, делая их невозвратными.
Спасибо за статью. Добавил кармы, теперь можете перенести в блог по Regexp
А что, парсеры уже отменили?
Можно еще такой вариант решения (php 5.2.8)
/"((?<=\\\)"|[^"])*"/
Это сделано с помощью позитивной ретроспективной проверки, фактически: Кавычка, (сколько угодно символов, которые являются или не-кавычкой, или кавычкой, но имеющей перед собой обратный слэш), кавычка
/"((?<=\\\)"|[^"])*"/
Это сделано с помощью позитивной ретроспективной проверки, фактически: Кавычка, (сколько угодно символов, которые являются или не-кавычкой, или кавычкой, но имеющей перед собой обратный слэш), кавычка
Данный вариант не будет работать в 100% случаев. Например:
"abc\\" — строка из 4х символов (последний: слэш) — не будет отпарсена правильно
А вот вариант, приведённый автором в конце статьи, будет работать корректно.
"abc\\" — строка из 4х символов (последний: слэш) — не будет отпарсена правильно
А вот вариант, приведённый автором в конце статьи, будет работать корректно.
Прочтите ниже вопрос netlink и мой ответ на него. Вариант korvin0 корректен, а цепочка
не содержит текст в кавычках, если строго следовать описанным в статье правилам.
"abc\\"
не содержит текст в кавычках, если строго следовать описанным в статье правилам.
Отлично! Все подробно и по полочкам. Сейчас в PHP экспериментировать буду.
НЛО прилетело и опубликовало эту надпись здесь
Там 3 разных «решения», вы про какое?
Впрочем, про какое бы решение ни шла речь, вы заметили тонкость: решение с *+ и решение в конце статьи работают просто-напросто по-разному. Цепочка
не соответствует регексу
однако соответствует регексу
В первом случае бэкслэш экранирует исключительно кавычку, и это "корректно", т. к. согласуется с условиями нашей задачи. Мы ничего не говорили о том, что бэкслэш может экранировать что бы то ни было кроме кавычки. Поэтому 1-й бэкслэш воспринимается как обычный одиночный символ, 2-й бэкслэш экранирует следующую за ним кавычку, а… а закрывающей-то кавычки нет! Поэтому соответствия (матча) регексу нет.
Во втором случае бэкслэш экранирует любой символ (а не только кавычку), и это "корректно", потому что это то, к чему мы все привыкли. 1-й бэкслэш в цепочке экранирует 2-й бэкслэш, а за ними идёт закрывающая кавычка… всё в порядке, есть матч.
Т. е. в обоих случаях всё «корректно», только переменная «корректно» меняет значение между случаями ;-)
С другой стороны, наполовину полный стакан всегда наполовину пуст, поэтому, если у вас плохое настроение, то у вас есть полное право сказать, что тут всё в дюпель не правильно: либо 2-е решение не решает задачу, либо сама задача поставлена криво ;-)
В общем, на самом деле всё не так, как в действительности ;-)
И спасибо за комментарий. На одном из моих любимых телеканалов есть лозунг: «Question everything». So thank you for questioning my regexes, mate :-)
Впрочем, про какое бы решение ни шла речь, вы заметили тонкость: решение с *+ и решение в конце статьи работают просто-напросто по-разному. Цепочка
aaa="bbb\\"
не соответствует регексу
/ " ( \\" | [^"] )*+ " /x
однако соответствует регексу
/ " ( [^"\\] | \\. )* " /x
В первом случае бэкслэш экранирует исключительно кавычку, и это "корректно", т. к. согласуется с условиями нашей задачи. Мы ничего не говорили о том, что бэкслэш может экранировать что бы то ни было кроме кавычки. Поэтому 1-й бэкслэш воспринимается как обычный одиночный символ, 2-й бэкслэш экранирует следующую за ним кавычку, а… а закрывающей-то кавычки нет! Поэтому соответствия (матча) регексу нет.
Во втором случае бэкслэш экранирует любой символ (а не только кавычку), и это "корректно", потому что это то, к чему мы все привыкли. 1-й бэкслэш в цепочке экранирует 2-й бэкслэш, а за ними идёт закрывающая кавычка… всё в порядке, есть матч.
Т. е. в обоих случаях всё «корректно», только переменная «корректно» меняет значение между случаями ;-)
С другой стороны, наполовину полный стакан всегда наполовину пуст, поэтому, если у вас плохое настроение, то у вас есть полное право сказать, что тут всё в дюпель не правильно: либо 2-е решение не решает задачу, либо сама задача поставлена криво ;-)
В общем, на самом деле всё не так, как в действительности ;-)
И спасибо за комментарий. На одном из моих любимых телеканалов есть лозунг: «Question everything». So thank you for questioning my regexes, mate :-)
Весьма любопытный материал, спасибо. А можете привести более иллюстративный пример регулярки, где эта фича будет наиболее красивым решением?
Мне кажется, что «сверхжадность» — это, скорее, необходимое зло, чем что-то красивое. Это как каска на голове или страховка: с ними неудобно, но они предотвращают «бааальшие» проблемы.
В качестве «иллюстративного» примера: попробуйте написать регекс, который матчит текст в скобках, причем внутри скобок могут быть вложенные скобки, например:
тут регекс должен найти аргумент функции log.
Если вы напишете этот регекс без сверхжадных квантификаторов (и без атомарной группировки, которая их обобщение), то, скорее всего, ваш регекс умрёт (будет матчить невыносимо долго) уже на «невалидной» цепочке в 30-40-80 символов.
Но давайте я об этом напишу в следующей заметке через ~ неделю, ок?
В качестве «иллюстративного» примера: попробуйте написать регекс, который матчит текст в скобках, причем внутри скобок могут быть вложенные скобки, например:
log((4 + k/3) * tan(2*phi) + sin((psi - theta)/2))
тут регекс должен найти аргумент функции log.
Если вы напишете этот регекс без сверхжадных квантификаторов (и без атомарной группировки, которая их обобщение), то, скорее всего, ваш регекс умрёт (будет матчить невыносимо долго) уже на «невалидной» цепочке в 30-40-80 символов.
Но давайте я об этом напишу в следующей заметке через ~ неделю, ок?
Очень познавательно, но сама по себе фича ужасна, так как разрушает декларативность языка регэкспов. Результат начинает зависеть, например, от порядка, в котором перечислены альтернативы — в общем, применять такое надо только если больше ничего не помогает.
Отличная статья! Автору спасибо.
Интересная статья, спасибо.
К информации, в статье на Википедии посвященной регуляркам — Регулярное_выражение наткнулся еще на одно определение сверхжадных квантификаторов — «Ревнивая квантификация»
К информации, в статье на Википедии посвященной регуляркам — Регулярное_выражение наткнулся еще на одно определение сверхжадных квантификаторов — «Ревнивая квантификация»
«Ревнивая» — это забавно :)
Такие термины обычно получаются, когда люди пользуются двуязычными словарями.
В русском языке просто нет аналога английского слова possessive, которое означает
Значение 1, действительно, близко по смыслу к русскому «ревнивый». Но в possessive quantifier используется, естественно, 2-е значение («владея» куском строки, оно не хочет отдавать его другим частям регекса), для которого в русском аналога нет, разве что «жадина», но слово «жадный» уже занято другим термином. При написании заметки я думал над синонимами «жадины», от которых можно образовать прилагательные. Но увы, получалась полная жесть: скряжные и сквалыжные квантификаторы 8-)
Можно извратиться также, использовав 3-е значение: притяжательные квантификаторы. А если кто-то возразит, то «неопровержимо» «доказать» свое мнение ссылкой на двуязычный словарь
8-)
Такие термины обычно получаются, когда люди пользуются двуязычными словарями.
В русском языке просто нет аналога английского слова possessive, которое означает
possessive (adjective)
1 wanting someone to have feelings of love or friendship for you and no one else
possessive of/about
She was terribly possessive of our eldest son.
2 unwilling to let other people use something you own
possessive of/about
He's so possessive about his new car.
3 technical used in grammar to show that something belongs to someone or something
possessive pronoun/form/case etc
the possessive pronouns 'ours' and 'mine'
Значение 1, действительно, близко по смыслу к русскому «ревнивый». Но в possessive quantifier используется, естественно, 2-е значение («владея» куском строки, оно не хочет отдавать его другим частям регекса), для которого в русском аналога нет, разве что «жадина», но слово «жадный» уже занято другим термином. При написании заметки я думал над синонимами «жадины», от которых можно образовать прилагательные. Но увы, получалась полная жесть: скряжные и сквалыжные квантификаторы 8-)
Можно извратиться также, использовав 3-е значение: притяжательные квантификаторы. А если кто-то возразит, то «неопровержимо» «доказать» свое мнение ссылкой на двуязычный словарь
8-)
Автор — ты молодец.
Спасибо что не пожалел времени написать!
+1
Спасибо что не пожалел времени написать!
+1
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Сверхжадные квантификаторы