elenaphotovrn.ru

Жадный userinfo php. Жадные и ленивые квантификаторы в регулярных выражениях. Регулярные выражения в PHP

Регулярные выражения, это очень мощный, но в то же время сложный для понимания, инструмент обработки строк. Опишу основные моменты. Регулярное выражение это шаблон строки. По этому шаблону можно искать вхождения, производить замену, проверять на соответствие шаблону.

Правила составление шаблона (pattern)

Границы шаблона должны обозначаться определенными символами, часто используют "/ ", но я предпочитаю использовать "# " потому, что от обилия прямых/обратных слешей может в глазах зарябить, а "решетки" обычно больше нигде не используются. Итак: "#ТутТелоРегулярногоВыражения# "

Внутри регулярного выражения используются скобки - это подвыражения, с которыми можно производить манипуляции, пример:

#^/catalog/(+)/(+)\.html.*#

Это выражение предназначено для получения параметров в строке URL . В начале строки идет спецсимвол "^ " - это означает начало строки. Далее идет "/catalog/ " - тут нет спецсимволов, это просто текст, который должен содержатся в строке. Затем встретили круглые скобки, т.е. дошли до первого подвыражения. В квадратных скобках обозначаются множество символов, которые могут быть в строке в этом месте. Знак "- " означает перечисление. Знак "\ " экранирует специальные символы. Таким образом, в первом подвыражении у нас могут идти БОЛЬШИЕ и маленькие буквы латинского алфавита, цифры от 0 до 9, знак подчеркивания, тире и точка. Тире и точка - это спецсимволы, но здесь они экранированы, поэтому здесь это просто символы. После квадратных скобок идет знак "+ " - это значит предыдущий символ (а у нас это множество символов заданное в квадратных скобках) может идти 1 или больше раз. Затем идет "/ " - это просто символ, и аналогичное второе подвыражение. Затем идет "\.html ", что означает текст ".html ". А затем спец символы ".* " точка означает любой символ, а звездочка любое количество предыдущего символа. Т.е. после ".html " может идти все что угодно.

Указание количества, квантификаторы

Выше мы уже рассмотрели такие символы, указывающие количество предыдущих символов, как + и * . Приведем все возможности указания количества:

Спецсимволы

Для некоторых групп символов есть специальные сокращения:

"Жадность"

Рассмотрим понятие жадности регулярного выражения. Например есть строка:

#()#

Читаем: подвыражение:

Вроди все верно, подвыражение подходит под:

Но оно также подходит под:

Его то мы и получим, т.к. регулярные выражения по умолчанию "жадные". Снять жадность можно с помощью модификатора "U ", вот так:

#()#U

Модификаторы

После регулярного выражения могут идти модификаторы: "#ТутТелоРегулярногоВыражения#ТутМодификаторы " Виды модификаторов:

i Включает режим case-insensitive, т.е. большие и маленькие буквы в выражении не различаются.
m Указывает на то, что текст, по которому ведется поиск, должен рассматриваться как состоящий из нескольких строк. По умолчанию механизм регулярных выражений рассматривает текст как одну строку вне зависимости от того, чем она является на самом деле. Соответственно метасимволы "^" и "$" указывают на начало и конец всего текста. Если же этот модификатор указан, то они будут указывать соответственно на начало и конец каждой строки текста.
s По умолчанию метасимвол ". " не включает в свое определение символ перевода строки. Указание этого модификатора снимает это ограничение.
U Снимает жадность регулярного выражения
u Включает работу регулярных выражений с кириллицей в UTF-8 , иначе работает не корректно.

php Функции для работы с регулярными выражениями

preg_replace

Поиск и замена:

Preg_replace (mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]]);

Каждое значение может быть строкой или массивом, в случае, если $subject массив - возвращается массив, иначе строка

preg_split

Разбивает строку по регулярному выражению:

Preg_split (string $pattern , string $subject [, int $limit = -1 [, int $flags = 0 ]]);

Возвращает массив, состоящий из подстрок заданной строки subject , которая разбита по границам, соответствующим шаблону pattern .

Для заграничных гостей напечатали отдельное меню.

Идея разных прейскурантов далеко не нова. Например, на турецких курортах во многих магазинчиках три прайса: для местных, для немцев и для русских. Платежеспособность-то у всех разная. Вот и московский ресторан “Генацвале ” , забыв про грузинское гостеприимство, напечатал два варианта меню. Одно на русском языке с обычными ценами. Другое - на английском для иностранцев с ценами, задранными в два раза.

Просто чахохбили в заведении стоит 380 рублей. А за chahohbili надо уже заплатить 840 rub. Видимо, за блюдо "в переводе".

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

Прокололись ребята “Генацвале ” , когда случайно дали журналисту Станиславу Натанзону оба варианта. Внимательный гость и обнаружил подлог.

"Они (иностранные фанаты - Авт.) заплатят вам ваш дабл-прайс, ваши счета за подорожавший в пять раз клоповник. Они выложат бабло - и пойдут дальше веселиться. Пока вы сальными пальцами перелистываете барыши от "терпил иностранных". Потому что они понимают, что веселье - навсегда, а деньги - на миг" , - так обратился в соцсети Натанзон к столичной индустрии сервиса.

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

Я говорю вам, как есть: у нас ничего подобного не происходит, - ответил представитель “Генацвале ” на вопрос, почему ресторан начал баловаться двойными меню.

Хоть рестораторы и отказались признавать свою вину, но гневить народ дальше не стали. От высоких цен для иностранцев заведение отказалось. Скорая проверка Роспотребнадзора не нашла нарушений.

"Информация в СМИ о фактах различия цен в англоязычном и русском вариантах меню в ресторане Москвы при проверках не подтвердилась" , - заявили в ведомстве.

Сейчас инспекторы проверяют вообще все рестораны вокруг Лужников, чтобы история с двойными ценами не повторилась.

Два меню с разными ценами - это нарушение закона о правах потребителей, - рассказал адвокат Дмитрий Лесняк. - Штраф выписывается по статье 14.15 КоАП за "нарушение правил продажи отдельных видов товаров" . Ресторан может заплатить от 10 до 30 тысяч рублей.

КАК ЕЩЕ ОБМАНЫВАЮТ ТУРИСТОВ

Самые шальные деньги сейчас зашибают таксисты. В ход идут вообще все уловки.

Самое распространенное: заломить несусветную цену. Иностранцы не знают, сколько у нас стоит поездка, поэтому за дорогу из аэропорта готовы отдать 5 тысяч рублей. Хотя обычно за аналогичный рейс просят не больше 1400 рублей. Только пассажиров приходится брать не через агрегаторы, а самим искать у тротуара.

Еще вариант: можно сказать, что счетчик показывает стоимость поездки не в рублях, а в валюте. Давайте не 230 рублей, а 230 евро. Одно хорошо - на такой бессовестный обман решаются далеко не все. Да и обмануть получается не каждого туриста. Иностранцы тоже не дураки и умеют считать деньги.

Я когда-то писал о . Так вот, мы с Вами там рассмотрели только "жадных " представителей. Однако, не всегда их "жадность " нам помогает, очень часто она и вредит. Чуть ниже я покажу пример, где чётко видно то, что они иногда делают, а также покажу как уменьшить их пыл и сделать квантификаторы повторений "ленивыми" .

Давайте разберём простой и уже ставший классическим пример:

$str = "Небольшая строка c жирным выделением.";
.*<\/b>
echo $result_str;
?>

Возможно, Вы ожидаете что-то наподобие этого: "Небольшая здесь_жирное_выделение с здесь_жирное_выделение выделением ". То есть просто замена содержимого внутри тега <b > на заданную нами строку вместе с самим тегом. Однако, это не совсем так, поскольку здесь вступает в игру "жадность квантификаторов ". И в результате замена была не внутри каждого тега <b >, а от самого первого открывающего тега до самого последнего закрывающего. В этом и состоит жадность.

Вот как надо писать данный код, чтобы замена происходила так, как мы хотим:

$str = "Небольшая строка c жирным выделением.";
$result_str = preg_replace("/.*?<\/b>/i", "здесь_жирное_выделение", $str);
echo $result_str;
?>

Всё, что мы изменили это регулярное выражение, поставив после квантификатора повторений ".* " знак вопроса, который как раз и делает квантификатор "ленивым" . Теперь результатом будет: "Небольшая здесь_жирное_выделение c здесь_жирное_выделение выделением. ", чего мы и пытались добиться.

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

О регулярных выражениях.

Регулярные выражения - мощный гибкий инструмент для синтаксического анализа текста в соответствии с определенным шаблоном.

Шаблон
- строка символов, спецсимволов и модификаторов, описывающих правила, которым должен соответствовать разбираемый текст.

Синтаксис регулярных выражений .

Это раздел о том, из чего состоят шаблоны.
Любой шаблон должен быть ограничен символами-ограничителями. В качестве таких символов можно использовать любой не буквенно-цифровой символ кроме "\".
Не рекомендуется использовать в качестве ограничителей и другие специальные символы, в виду того их использование внутри шаблона станет неудобным. Предпочтительнее всего использовать символ /, потому что он не выполняет никаких специальных функций.
Символ, используемый как ограничитель шаблона внутри шаблона должен экранироваться.
Пример: "/pattern/i" - соответствует строке, в которой есть слово pattern. i - это модификатор. Забегая вперед, скажу, что он означает регистронезависимое сравнение.

1 - Спецсимволы.
Сначала о них, потому что мне будет легче описать остальное.
\ - символ экранирования.
Пример: "/qwe\/rty/" - соответствует строке, в которой есть qwe/try. Символ / мы заэкранировали, после чего он перестал выполнять в данном месте свое специальное значение (он являлся ограничителем шаблона).
^ - символ начала данных.
$ - символ конца данных.
Пример: "/^pattern$/" - Соответствует строке, точно совпадающей с словом pattern. Т.е. с буквы p строка начинается и после n заканчивается.
. - любой символ, кроме перевода строки. Но есть модификатор, при использовании которого перевод строки тоже относится к "любым" символам.
Пример: "/pat.ern/" - Соответствует и строке, содержащей pattern, или patdern, или pat3ern...
- внутри этих скобок перечисляются символы, любой один символ из которых может стоять на данном месте. Это называется символьным классом. Спецсимволы, написанные в ведут себя немного по-другому. Это я напишу.
Пример: "/patrn/" - под соответствие попадут только строки, содержащие patarn, patorn или patern.
| - Или. Пример ниже.
() - подмаска.
? - одно или ноль вхождений предшествующего символа или подмаски.
* - любое количество вхождений предшествующего символа или подмаски. В том числе и ноль.
+ - одно или более вхождений.
Пример: "/as+(es|du)?.*r/" - Буква а, потом одна или больше букв s, после этого сочетание es или du может быть один раз, а может м ни разу, потом любое количество любых символов и буква r.
Здесь же скажу про еще одно значения символа?. Метасимвол звездочка по умолчанию жадный (и другие тоже). Это значит, что в нашем примере вот этой части ".*r" будет соответствовать, например, подстрока asdrfsrsfdr. Как видно, до последней буквы r в нее попало еще две. Вот эту жадность можно выключить. Т.е. шаблон станет соответствовать только подстроке asdr. До первого r. Для этого надо в до того места где необходимо отключить жадность поставит модификатор (?U) . Вот еще одно применение символам? и ().
{a,b} - количество вхождений предшествующего символа или подмаски от а до б. Если б не указан, считается, что верхней границы нет. Например, * - то же самое, что {0,}. ? - то же, что {0,1}. {5,7} - 5,6 или 7 повторений.

a) Спецсимволы внутри символьного класса.
^ - отрицание.
Пример: [^da] - соответствует любому символу кроме d и a.
Пример: [^^] - соответствует любому символу кроме ^.
Пример: - соответствует любому символу из перечисленных трёх. [\^da] - то же самое.
В последнем примере, как видно символ стоит не в начале перечисления и свою метафункцию теряет. И экранировать его, кстати, тоже тут не надо.
- - внутри символьного класса означает символьный интервал.
Пример: - соответствует любому символу от 0 до 9 и от a до e. Если в символьном классе надо перечислить сам символ дефиса, то следует либо заэранироватьего, либо разместить перед ].
Осторожно в символьном классе надо использовать символ \. Если его поставить перед ], она окажется заэкранирована. Также окажется заэкранированным любой символ, который может быть заэкранирован. Иначе символ \ является обычным символом.
Символ $ тоже является обычным символом внутри символьного класса. И скобки тоже.

б) Символ \ . Одна из его функций - снятие специального значения с спецсимволов. А другая, наоборот придание специальных функций обычным символам.
\cx - ctrl + x. На месте x может быть любой символ.
\e - escape.
\f - разрыв страницы.
\n, \r, \t - это нам и так привычно. Перевод строки, возврат каретки и табуляция.
\d - любой символ, означающий десятичную цифру.
\D - любой символ, не означающий десятичную цифру.
\s - любой пробельный символ.
\S - не пробельный.
\w - любая цифра, буква или знак подчеркивания.
\W - любой символ, но не \w.
\b - граница слова. Можно использовать вместо \w\W или \W\w или ^\w или \w$
\B - не граница слова.
Две последние конструкции не соответствуют никаким реальным символам.
\xHH - символ с шестнадцатиричным кодом HH. x - это именно буква икс.
\DDD - символ с восьмиричным кодом DDD. Или ссылка на подмаску.

По поводу ссылки на подмаску: "/({2,3}).\1/" - 2 или 3 символа от 0 до 9, потом любая последовательность символов и те же 2 или 3 конкретных символа, которые соответствовали подмаске. То есть строка "as34sdf34" - подойдет. Там 34, и там. А "sd34dg32" - нет.
Если анализатор находит \x, он считывает максимальное количество последующих символов, которые могут быть шестнадцатиричным числом. Максимальное - это не больше двух. Если из три, то считается два, если меньше - то сколько есть.
Если анализатор находит \0, он поступает аналогично. Только считывает не 16ричные, а восмеричные цифры. До двух штук. То есть \0\x\0325 означает два символа с кодом ноль, символ с восьмеричным кодом 32 и пятерка.
Если после слеша стоит отличная от нуля цифра, то ту посложнее. Вот напишем такую вещь: \40. Если в шаблоне есть 40 подмасок, то это будет воспринято как ссылка на 40ю подмаску. Сороковую - в десятичной системе счисления. Если же подмасок меньше, то это будет воспринято как символ с восьмеричном кодом 40.
\040 - всегда символ с кодом и восьмеричным 40.
\7 - всегда ссылка на подмаску.
\13 - в зависимости от ситуации.
В символьном классе возможно указывать символьные диапазоны с помощью из кодов: [\044-\056]
Стоит также отметить, что ссылок на подмаски не может быть больше, чем 99.

2 - Обычные символы.
Это символы, не являющиеся специальными.

3 - Модификаторы.
Указываются они либо в скобках, например так: (?Ui), либо после закрывающего символа "/pattern/Ui".
i - регистронезависимость.
U - инвертирует жадность.
m - многострочный поиск.
s - если используется, то символ. соответствует и переводу строки. Иначе она ему не соответствует.
x - заставляет игнорировать все неэкранированные пробельные символы, если они не перечислены в символьном классе. Удобно, когда энтерами и пробелами вы хотите навести удобночитаемость в регулярке.
При использовании модификаторов, можно использовать знак "-" для отключения модификатора. (?m-i) - Bключаем многострочный поиск и отключаем регистронезависимый.
Здесь надо сказать, что все модификаторы что-то включают. Или отключают, если указаны с минусом. А вот U инвертирует. Т.е. если была жадность включена, он выключит без всяких минусов.

4 - Утверждения.
Утверждения - это проверки касательно символов, идущих до или после текущей позиции сопоставления. Например, \b - это утверждение, что предыдущий символ словесный, а следующий - нет, либо наоборот. Но это как бы встроенное утверждение, а мы тут сейчас свои собственные научимся писать.
Утверждения касательно последующего текста начинаются с (?= для положительных утверждений и с (?! для отрицающих утверждений.
Утверждения касательно предшествующего текста начинаются с (?<= для положительных утверждений и (?
Например, "/(? (?<=\d{3})(? Утверждения могут быть вложенными, причем в произвольных сочетаниях: (?<=(?

a) Условные подмаски.
По-моему, этого достаточно: (?(condition)yes-pattern|no-pattern)
Пример: (?(?=\d)u|p). (?=\d) - это условие. Мы утверждаем, что после этого места идет цифра. Если оно истинно, то на данном месте должна стоять буква u. Иначе - p.

5 - Комментарии.
Комментарии начинаются с (?# и продолжаются до ближайшей закрывающей скобки. Так же как /* */ в PHP - без учета вложенности.

Вот и всё. Этой теории, в принципе, должно хватить.

Функции PHP для работы с регулярными выражениями.

<<< Назад Содержание Вперед >>>
Есть еще вопросы или что-то непонятно - добро пожаловать на наш
Загрузка...