regulyarnyie-vyirazheniya-osnovyi (852744), страница 16
Текст из файла (страница 16)
Ленивые квантификаторыСинтаксис Описание??Ленивый поиск, при котором предыдущий символ или группа можетвстретиться в данной позиции нуль или один раз+?Ленивый поиск, при котором предыдущий символ или группа можетвстретиться в данной позиции один или более раз*?Ленивый поиск, при котором предыдущий символ или группа можетвстретиться в данной позиции нуль или более раз{ п} ?Ленивый поиск ровно п повторений предыдущего символа или группы{ п, } ?Ленивый поиск п или более повторений предыдущего символа или группы{ т, п} ?Ленивый поиск не менее чем п и не более чем т повторений предыдущегосимвола или группыСверхжадные квантификаторыСверхжадный поиск, как и жадный, пытается обнаружить совпадение с как можнобольшим количеством символов, однако, в отличие от него, не использует перебор с возвратом (бектрекинг). Сверхжадное выражение не отдает ничего из того, с чем ему удаетсясовпасть.
Оно исключительно эгоистично. Именно поэтому его и называют сверхжаднь�м.Заняв боевую стойку, оно не отдает ни пяди завоеванной территории. В сверхжадныхквантификаторах положительно то, что, благодаря выполнению поиска без возврата, ониработают быстрее жадных квантификаторов, а если даже и не находят совпадений, то этотакже обнаруживается очень быстро.Честно говоря, приведенные в книге примеры вряд ли позволят вам ощутитьв полной мере различия в поведении жадных, ленивых и сверхжадных квантификаторов. Но, по мере того как вы будете приобретать опыт и вам придется задумываться о производительности, знание этих различий будет иметьдля вас важное значение.Чтобы это понять, сравните работу двух выражений, в одном из которых литеральный нуль указан в начале, а в другом - в конце выражения. Убедитесь в том, что в приложении Reggy установлен флажок Match AII, и введите следующее выражение (начальный нуль):О.*+Что при этом происходит? Выделяется вся строка с нулями.
Совпадение было найдено. Создается впечатление, будто сверхжадный поиск приводит к тому же результату,92Гnава 7. Квантификаторычто и жадный, однако есть одна тонкость: он не сопровождается перебором с возвратом.Сейчас мы это докажем. Введите следующее выражение (конечный нуль):.*+ОСовпадения отсутствуют.
Объясняется это тем, что не выполнялся поиск с возвратом.Это выражение "проглотило" весь ввод, даже не подумав о том, чтобы оглянуться назад.Оно растратило свое наследство из-за разгульного образа жизни и не смогло найти конечный нуль. Оно просто не знает, где его искать. Если же вы уберете знак+, то получаемое при этом следующее выражение сможет найти все нули, поскольку оно будет делатьэто уже в режиме жадного сопоставления:.*ОСверхжадные квантификаторы имеет смысл использовать в тех случаях, когда вамизвестно, что собой представляет тестируемый текст, и вы знаете, где следует искать совпадения.
В подобных ситуациях аппетит квантификаторов этого типа вас не может смутить, поскольку он обеспечивает более высокую производительность операций поиска.Перечень сверхжадных квантификаторов приведен в табл. 7.4.Таблица 7 .4. СверХ)l(адные квантификаторыСинтаксисОписание?+Сверхжадный поиск, при котором предыдущий символ или группа можетвстретиться в данной позиции нуль или один раз++Сверхжадный поиск, при котором предыдущий символ или группа можетвстретиться в данной позиции один или более раз*+Сверхжадный поиск, при котором предыдущий символ или группа можетвстретиться в данной позиции нуль или более раз{n}+Сверхжадный поиск ровно n повторений предыдущего символа или группы{n, )+Сверхжадный поиск n или более повторений предыдущего символаили группы{m,n}+Сверхжадный поиск не менее чем n и не более чем m повторений предыдущего символа или группыСледующая глава посвящена обсуждению различных видов контекстной проверкитекста.О чем вы узнапи в rпаве 7• Чем различаются между собой жадный, ленивый и сверхжадный квантификаторы.• Как найти одно или более вхождений символа (+).• Как найти необязательный символ (отсутствие или однократное вхождение символа,?).Гnава 7.
Квантификаторы93• Как найти отсутствие или многократное вхождение символа ( \ * ).• Как используются квантификаторы { m, n}.• Как используются жадные, ленивые (нежадные) и сверхжадные квантификаторы.На заметкуПриведенная в начале главы цитата взята из следующего источника:• Ken Thompson, QED Text Editor (Murray Hill, NJ, Bell Labs, 1970), р.
3 (http: //cm.bell-labs. com/cm/cs/who/dmr /qedman .pdf).94Гnава 7. КвантификаторыГЛАВА 8Группы проверкиГрупт,1 проверки (lookarounds), называемые также группами просмотра, - это rруnпыбез захвата, которые сопоставляют текст с шаблоном с учетом того, что именно они находят впереди или позади шаблона.
Груnпы проверки также считаются условиями с нулевойдлиной совпадения (zero-width assertions).К rруnпам проверки относятся:• груnпы с положительной опережающей проверкой;• груnпы с отрицательной опережающей проверкой;• груnпы с положительной ретроспективной проверкой;• группы с отрицательной ретроспективной проверкой.В этой главе будет продемонстрировано, как работает каждый из перечисленных видов проверки. Мы начнем с использования настольного приложения RegExr, но затем переключимся на Perl и ack (утилите grep о группах проверки ничего не известно). Нашимрабочим текстом по-прежнему будет уже набившая вам оскомину поэма Кольриджа.Поnожитеnыая опережающая проверкаПредположим, вы хотите найти все вхождения слова ancyent, за которым следует слово marinere (я использую эти слова в том архаичном написании, в каком они встречаютсяв файле).Прежде всего посмотрим, как все это работает в приложении RegExr.
Введите в верхнее текстовое поле следующий нечувствительный к регистру букв (опция i) шаблон:IO•(?i)ancyent (?=marinere)J,,.....В приложении RegExr можно задать нечувствительность шаблона к региструбукв другим способом. Для этого достаточно установить флажок ignoreCase,щелкнув на квадратике рядом с надписью. Можете использовать тот способ,который для вас наиболее удобен.Поскольку выбран нечувствительный к регистру режим (? i), вы не должны беспокоиться о том, какой регистр букв использовать в шаблоне. Ваша цель - найти строки,в которых имеется слово ancyent, за которым следует слово marinere. Результат выделится цветом в текстовой области ниже шаблона (рис. 8.1), но выделена будет лишь перваячасть шаблона (ancyent), тогда как шаблон опережающей проверки (Marinere) останетсяневыделенным.RogExrRep�ceMatchSampl@s("j)ancyent (?=marinere)'--' ЩnoreC.se:� globalHySavedCommun1tyshow alli;_J extended..........idot.all� mulЫ1neТНЕ RIME OF ТНЕ ANCYENТ MдRINERE, IN SEVEN PARTS.\w\WARGUMENТ.\dHow а Ship having passed the Une was dril.'en Ьу Storms to the cold Countrytowards the South Pole; and hov, from thence she made her course to the tropical\ОLatitude of the Gгeat Pacific Ocean; and of the strange things that befell: and invA,st milnner the Ancy@nt Marinere came back to his ON1 Country.\s\S(АВС](.1t is an a.ncyent Marinere,And he stoppeth one of three:''Ву thy long grey beard and thy glittering еуе"No\'I ,�erefore stoppest me"(лдвс][a-z]M.-tthц any ch�r•c.Ь!r except for l1nebreaks if dotall ,s falн�."The Bridegroom's doors are open'd vltde"And I am next of kin:"The Guests are met.
the Feast is set,··"May'st hear thf! merry dln.--RegExp:P1)ancyent (?=mannere), gpatt�rn: ('l)sncyent ('.cm.snnere)flag•: g1 c•phlrи1g groups:group 1: 1"71)Рис. 8.1. Положительная опережающая проверка в RegExrА теперь выполним положительную опережающую проверку (positive lookahead; другое название - просмотр вперед) с помощью Perl.
Для этого можно использовать следующую команду:perl -ne 'print if /(?i)ancyent (?=marinere)/' rime.txtРезультат будет выглядеть примерно так.ТНЕ RIМE OF ТНЕ ANCYENT МARINERE, IN SEVEN PARTS.How а Ship having passed the Line was driven Ьу Stormsto the cold Country towards the South Pole; and how fromthence she made her course to the tropical Latitude of theGreat Pacific Ocean; and of the strange things that befell;and in what manner the Ancyent Marinere came back to hisown Country.It is an ancyent Marinere,"God save thee, ancyent Marinere!"I fear thee, ancyent Marinere!В поэме есть пять строк, в которых слово ancyent появляется непосредственно перед словом marinere.
Что если бы мы хотели проверить лишь то, начинается ли слово,96Гnава 8. Группы проверкиследующее за словом ancyent, с буквы т, независимо от ее регистра? Это можно сделатьс помощью следующей команды:perl -ne 'print if /(?i)ancyent (?=m)/' rime.txtВ таком случае вы получите дополнительно к предыдущему выводу следующие строки, в которых за словом ancyent следуют слова тап и Мап.And thus spake оп that ancyent man,And thus spake оп that ancyent Man,Входящая в Perl утилита ack также поддерживает положительную опережающую проверку. Интерфейсы командной строки утилит ack и grep очень схожи между собой.Выполнив следующую команду, вы получите результат, представленный на рис.