Mastering Regular Expressions


Third Edition


Jeffrey E.F. Friedl


image


Регулярные выражения


Третье издание


Джеффри Фридл


image

Санкт-Петербург–Москва 2008

Джеффри Фридл

Регулярные выражения, 3-е издание

Перевод Е. Матвеева и А. Киселева

Главный редактор А. Галунов Зав. редакцией Н. Макарова Научный редактор Б. Попов

Редактор Ю. Бочина

Корректор С. Минин

Верстка Д. Орлова

Фридл Дж.

Регулярные выражения, 3-е издание. – Пер. с англ. – СПб.: Символ-Плюс, 2008. – 608 с., ил.

ISBN-13: 978-5-93286-121-9

ISBN-10: 5-93286-121-5

Книга Джеффри Фридла «Регулярные выражения» откроет перед вами секрет высокой производительности. Тщательно продуманные регулярные выраже- ния помогут избежать долгих часов утомительной работы и решить проблемы за 15 секунд. Ставшие стандартной возможностью во многих языках програм- мирования и популярных программных продуктах, включая Perl, PHP, Java, Python, Ruby, MySQL, VB.NET, C# (и других языках платформы .NET), регу- лярные выражения позволят вам автоматизировать сложную и тонкую обра- ботку текста.

В третье издание включена информация о PHP и его мощном механизме регу- лярных выражений. Кроме того, обновлены и дополнены сведения о других языках программирования, включая расширенное и углубленное описание пакета java.util.regex компании Sun, при этом особое внимание уделено раз- личиям между Java 1.4.2 и Java 1.5/1.6. Рассматривается принцип действия механизма регулярных выражений, сравниваются функциональные возмож- ности различных языков программирования и инструментальных средств, по- дробно обсуждается оптимизация, которая дает основную экономию времени! Вы научитесь правильно конструировать регулярные выражения для самых разных ситуаций и сможете сразу же использовать предлагаемые ответы для выработки элегантных и экономичных практических решений широкого круга проблем. Кроме того, автор демонстрирует наиболее распространенные ошибки и показывает, как их избежать.

ISBN−13: 978−5−93286−121−9

ISBN−10: 5−93286−121−5

ISBN 0−596−52812−4 (англ)

© Издательство Символ-Плюс, 2008

Authorized translation of the English edition © 2006 O’Reilly Media, Inc. This trans- lation is published and sold by permission of O’Reilly Media, Inc., the owner of all rights to publish and sell the same.

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

Издательство «Символ-Плюс». 199034, Санкт-Петербург, 16 линия, 7,

тел. (812) 324-5353, www.symbol.ru. Лицензия ЛП N 000054 от 25.12.98. Подписано в печать 25.07.2008. Формат 701001/16. Печать офсетная.

Объем 38 печ. л. Тираж 2000 экз. Заказ №

Отпечатано с готовых диапозитивов в ГУП «Типография «Наука» 199034, Санкт-Петербург, 9 линия, 12.



image

МОЕЙ

Ф у м и э


За смирение.

За то, что терпела меня все эти годы, пока я работал над книгой.


Оглавление


Предисловие 15

  1. Знакомство с регулярными выражениями 24

    Решение реальных задач 25

    Регулярные выражения как язык 27

    Аналогия с файловыми шаблонами 27

    Аналогия с языками 28

    Регулярные выражения как особый склад ума 29

    Для читателей, имеющих опыт работы

    с регулярными выражениями 29

    Поиск в текстовых файлах: egrep 30

    Метасимволы egrep 31

    Начало и конец строки 32

    Символьные классы 32

    Один произвольный символ 35

    Выбор 37

    Игнорирование различий в регистре символов 39

    Границы слов 39

    В двух словах 40

    Необязательные элементы 42

    Другие квантификаторы: повторение 43

    Круглые скобки и обратные ссылки 45

    Экранирование 47

    Новые горизонты 48

    Языковая диверсификация 48

    Смысл регулярного выражения 49

    Дополнительные примеры 49

    Терминология регулярных выражений 52

    Пути к совершенствованию 56

    Итоги 58

    Личные заметки 59

  2. Дополнительные примеры 61

    О примерах 62

    Краткий курс Perl 63

    Поиск по регулярному выражению 64

    Переходим к реальным примерам 66

    Побочные эффекты успешных совпадений 67

    Взаимодействие регулярных выражений с логикой программы 70

    Лирическое отступление 76

    Модификация текста с использованием регулярных выражений 77

    Пример: письмо на стандартном бланке 78

    Пример: обработка биржевых котировок 79

    Автоматизация редактирования 80

    Маленькая почтовая утилита 81

    Разделение разрядов числа запятыми 88

    Преобразование текста в HTML 97

    Задача с повторяющимися словами 108

  3. Регулярные выражения: возможности и диалекты 114

    История регулярных выражений 116

    Происхождение регулярных выражений 116

    На первый взгляд 123

    Основные операции с регулярными выражениями 126

    Интегрированный интерфейс 127

    Процедурный и объектно-ориентированный интерфейс 127

    Поиск с заменой 131

    Поиск и замена в других языках 133

    Итоги 135

    Строки, кодировки и режимы 135

    Строки как регулярные выражения 135

    Проблемы кодировки символов 140

    Юникод 141

    Режимы обработки регулярных выражений

    и поиска совпадений 145

    Стандартные метасимволы и возможности 149

    Представления символов 151

    Символьные классы и их аналоги 155

    Якорные метасимволы и другие проверки

    с нулевой длиной совпадения 169

    Комментарии и модификаторы режимов 176

    Группировка, сохранение, условные

    и управляющие конструкции 178

    Путеводитель по серьезным главам 184

  4. Механика обработки регулярных выражений 186

    Запустить двигатели! 186

    Два вида двигателей 186

    Новые стандарты 187

    Типы механизмов регулярных выражений 188

    С позиций избыточности 189

    Определение типа механизма 190

    Основы поиска совпадений 191

    О примерах 191

    Правило 1: более раннее совпадение выигрывает 191

    Компоненты и части двигателя 192

    Правило 2: квантификаторы работают максимально 195

    Механизмы регулярных выражений 198

    НКА: механизм, управляемый регулярным выражением 198

    ДКА: механизм, управляемый текстом 200

    Сравнение двух механизмов 200

    Возврат 202

    Крошечная аналогия 202

    Два важных замечания 204

    Сохраненные состояния 204

    Возврат и максимализм 207

    Подробнее о максимализме и о возврате 209

    Проблемы максимализма 210

    Многосимвольные «кавычки» 211

    Минимальные квантификаторы 212

    Максимальные и минимальные конструкции

    всегда выбирают совпадение 213

    О сущности максимализма, минимализма и возврата 215

    Захватывающие квантификаторы и атомарная группировка 216

    Захватывающие квантификаторы ?+, *+, ++ и {max,min}+ 219

    Возврат при позиционной проверке 220

    Максимальна ли конструкция выбора? 222

    Использование упорядоченного выбора 223

    НКА, ДКА и POSIX 225

    «Самое длинное совпадение, ближнее к левому краю» 225

    POSIX и правило «самого длинного совпадения,

    ближнего к левому краю» 226

    Скорость и эффективность 227

    Сравнение ДКА и НКА 229

    Итоги 232

  5. Практические приемы построения регулярных выражений 234

    Балансировка регулярных выражений 235

    Несколько коротких примеров 235

    Снова о строках продолжения 235

    Поиск IP-адреса 236

    Работа с именами файлов 239

    Поиск парных скобок 243

    Исключение нежелательных совпадений 245

    Поиск текста в ограничителях 246

    Данные и предположения 249

    Удаление пропусков в начале и конце строки 250

    Работа с HTML 251

    Поиск тегов HTML 251

    Поиск ссылок HTML 253

    Анализ HTTP URL 255

    Проверка имени хоста 255

    Поиск URL на практике 258

    Нетривиальные примеры 262

    Синхронизация 262

    Разбор данных, разделенных запятыми 266

  6. Построение эффективных регулярных выражений 274

    Убедительный пример 275

    Простое изменение – начинаем с более вероятного случая 276

    Эффективность и правильность 277

    Следующий шаг – локализация максимального поиска 277

    Возвращение к реальности 279

    Возврат с глобальной точки зрения 282

    POSIX НКА – работа продолжается 283

    Работа механизма при отсутствии совпадения 283

    Уточнение 284

    Конструкция выбора может дорого обойтись 285

    Хронометраж 286

    Зависимость результатов хронометража от данных 288

    Хронометраж в языке PHP 288

    Хронометраж в языке Java 289

    Хронометраж в языке VB.NET 291

    Хронометраж в языке Ruby 292

    Хронометраж в языке Python 293

    Хронометраж в языке Tcl 293

    Стандартные оптимизации 294

    Ничто не дается бесплатно 295

    Универсальных истин не бывает 296

    Механика применения регулярных выражений 296

    Предварительные оптимизации 297

    Оптимизации при смещении текущей позиции 301

    Оптимизации на уровне регулярных выражений 303

    Приемы построения быстрых выражений 309

    Приемы, основанные на здравом смысле 310

    Выделение литерального текста 312

    Выделение якорей 312

    Выбор между минимальными и максимальными

    квантификаторами 313

    Разделение регулярных выражений 314

    Имитация исключения по первому символу 316

    Использование атомарной группировки

    и захватывающих квантификаторов 317

    Руководство процессом поиска 317

    Раскрутка цикла 319

    Метод 1: построение регулярного выражения

    по результатам тестов 320

    Общий шаблон «раскрутки цикла» 322

    Метод 2: структурный анализ 325

    Метод 3: имена хостов Интернета 325

    Замечания 327

    Применение атомарной группировки

    и захватывающих квантификаторов 327

    Примеры раскрутки цикла 329

    Раскрутка комментариев С 331

    Исключение случайных совпадений 337

    Управление поиском совпадения 337

    Управление поиском = скорость 339

    Свертка 341

    Вывод: думайте! 342

  7. Perl 343

    Регулярные выражения как компонент языка 345

    Самая сильная сторона Perl 346

    Самая слабая сторона Perl 347

    Диалект регулярных выражений Perl 347

    Регулярные выражения – операнды и литералы 350

    Порядок обработки литералов регулярных выражений 354

    Модификаторы регулярных выражений 354

    Реrl’измы из области регулярных выражений 355

    Контекст выражения 356

    Динамическая видимость и последствия

    совпадения регулярных выражений 357

    Специальные переменные, изменяемые при поиске 362

    Оператор qr/…/ и объекты регулярных выражений 366

    Построение и использование объектов

    регулярных выражений 367

    Просмотр содержимого объектов регулярных выражений 369

    Объекты регулярных выражений и повышение

    эффективности 370

    Оператор поиска 370

    Операнд регулярное выражение 370

    Операнд целевой текст 372

    Варианты использования оператора поиска 374

    Интерактивный поиск – скалярный контекст

    с модификатором /g 377

    Внешние связи оператора поиска 382

    Оператор подстановки 383

    Операнд-замена 384

    Модификатор /e 385

    Контекст и возвращаемое значение 386

    Оператор разбиения 386

    Простейшее разбиение 387

    Возвращение пустых элементов 389

    Специальные значения первого операнда split 390

    Сохраняющие круглые скобки в первом операнде split 392

    Специфические возможности Perl 392

    Применение динамических регулярных выражений

    для поиска вложенных конструкций 394

    Встроенный код 397

    Ключевое слово local во встроенном коде 402

    Встроенный код и переменные my 405

    Поиск вложенных конструкций 407

    Перегрузка литералов регулярных выражений 409

    Ограничения перегрузки литералов регулярных выражений 412

    Имитация именованного сохранения 413

    Проблемы эффективности в Perl 416

    У каждой задачи есть несколько решений 417

    Компиляция регулярных выражений, модификатор /о, qr/…/

    и эффективность 418

    Предварительное копирование 425

    Функция study 429

    Хронометраж 431

    Отладочная информация регулярных выражений 431

    Последний комментарий 434

  8. Java 436

Диалект регулярных выражений 438

Поддержка конструкций \p{…} и \P{…} в Java 441

Завершители строк Юникода 442

Использование пакета java.util.regex 443

Метод Pattern.compile() 444

Метод Pattern.matcher() 445

Объект Matcher 446

Применение регулярного выражения 448

Получение информации о результатах 449

Простой поиск с заменой 451

Расширенный поиск с заменой 454

Поиск с заменой по месту 456

Область в объекте Matcher 457

Объединение методов в конвейер 463

Методы для построения сканеров 464

Другие методы Matcher 468

Другие методы Pattern 470

Метод split класса Pattern с одним аргументом 471

Метод split класса Pattern с двумя аргументами 472

Дополнительные примеры 473

Добавление атрибутов WIDTH и HEIGHT в теги <img> 473

Проверка корректности HTML-кода с использованием

нескольких регулярных выражений на один объект Matcher 475

Разбор данных CSV 476

Различия между версиями Java 477

Различия между 1.4.2 и 1.5.0 477

Различия между 1.5.0 и 1.6.0 480

9. .NET 481

Диалект регулярных выражений .NET 482

Замечания по поводу диалекта .NET 485

Использование регулярных выражений в .NET 490

Основные принципы работы с регулярными выражениями 490

Общие сведения о пакете 492

Краткая сводка основных объектов 494

Основные объекты 496

Создание объектов Regex 496

Использование объектов Regex 499

Использование объектов Match 507

Использование объектов Group 508

Статические вспомогательные функции 509

Кэширование регулярных выражений 510

Дополнительные функции 511

Нетривиальные возможности .NET 513

Сборки регулярных выражений 513

Поиск вложенных конструкций 515

Объект Capture 516

10. PHP 519

Диалект регулярных выражений PHP 521

Функциональный интерфейс механизма preg 524

Аргумент «шаблон» 525

Функции preg 531

preg_match_all 536

preg_replace 542

preg_replace_callback 548

preg_split 551

preg_grep 556

preg_quote 557

«Недостающие» функции preg 558

preg_regex_to_pattern 558

Проверка синтаксиса неизвестного шаблона 561

Проверка синтаксиса

неизвестного регулярного выражения 562

Рекурсивные регулярные выражения 563

Поиск совпадений с вложенными круглыми скобками 563

Никаких возвратов в рекурсии 566

Совпадение с парой вложенных скобок 566

Вопросы эффективности в PHP 566

Модификатор шаблона S: «Study» 567

Расширенные примеры 569

Разбор данных в формате CVS в PHP 569

Проверка тегированных данных на корректность

вложенных конструкций 570

Алфавитный указатель 575


Предисловие


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

Регулярные выражения поддерживаются многими программами (ре- дакторами, системными утилитами, ядрами баз данных и т. д.), но их возможности в полной мере проявляются в языках программирова- ния, в том числе Java и Jscript, Visual Basic и VBScript, JavaScript и ECMAScript, C, C++, C#, elisp, Perl, Python, Tcl, Ruby, PHP, sed и awk. Регулярные выражения занимают центральное место во мно- гих программах, написанных на этих языках.

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


Почему я написал эту книгу

Я завершил работу над первым изданием книги в конце 1996 года. Книга была написана потому, что она была действительно нужна. Хо- рошей документации по регулярным выражениям не существовало, поэтому большая часть их возможностей оставалась неиспользуемой. Впрочем, документации по регулярным выражениям хватало, но она фокусировалась на работе на «низком уровне». Если показать кому-ни- будь алфавит, трудно ожидать, что он сразу заговорит на новом языке.

Пять с половиной лет, прошедшие между публикациями первого и вто- рого изданий этой книги, отмечены ростом популярности Интернета и (вряд ли случайным) значительным расширением области примене-


ния регулярных выражений. Практически во всех языках и програм- мах поддержка регулярных выражений стала более мощной и вырази- тельной. Perl, Python, Tcl, Java и Visual Basic – во всех этих языках были созданы новые средства для работы с регулярными выражения- ми. Появились и завоевали популярность новые языки с поддержкой регулярных выражений (такие как Ruby, PHP и C#). Все это время ос- новные решаемые книгой вопросы – как правильно понимать регуляр- ные выражения и как извлечь из них максимальную практическую пользу – оставались важными и актуальными.

Но со временем первое издание стало морально стареть. Оно нуждалось в обновлении, которое позволило бы отразить новые языки и возмож- ности, а также возрастающую роль регулярных выражений в совре- менном Интернете. Второе издание книги вышло в 2002 году, когда появились принципиально новые версии java.util.regex, .NET Frame- work от Microsoft и Perl 5.8. Все они полностью были описаны во вто- ром издании книги. Единственное, о чем я сожалею, – это то, что я не- достаточно внимания уделил языку PHP. В течение всех четырех лет после выхода второго издания книги значение языка PHP устойчиво возрастало, поэтому я считаю своим долгом исправить этот недостаток.

В данном третьем издании языку PHP уделено углубленное внимание в первых главах; кроме того, появилась новая объемная глава, полно- стью посвященная регулярным выражениям в PHP и методам наибо- лее эффективного их использования. Помимо того, в этом издании глава, посвященная языку Java, была переписана и расширена с уче- том новых возможностей Java 1.5 и Java 1.6.


Для кого написана эта книга

Книга представляет интерес для всех, кто мог бы использовать регуляр- ные выражения в своей работе. Если вы еще не представляете, насколь- ко богатыми возможностями обладают регулярные выражения, для вас откроется целый новый мир. Книга расширит ваш кругозор, даже если вы считаете себя экспертом в области регулярных выражений. После выхода первого издания я получил немало сообщений электронной поч- ты типа «Я считал, что умею пользоваться регулярными выражения- ми, пока не прочитал эту книгу. Теперь я действительно умею».

Программисты, занимающиеся обработкой текста (например, веб-про- граммированием), найдут здесь многочисленные технические подроб- ности, рекомендации, советы, а самое главное – осознают новые воз- можности, которые можно немедленно применить на практике. Столь подробного и скрупулезного изложения материала вы просто не найде- те в других источниках.

Регулярные выражения – это абстрактная концепция, по-разному реализуемая в разных программах (которых гораздо больше, чем рас- смотрено в этой книге). Если вы поймете общую концепцию регуляр-


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


Как читать эту книгу

Эта книга может стать учебником, справочником или просто расска- зом – все зависит от того, как к ней подойти. Читатели, знакомые с ре- гулярными выражениями, обычно рассматривают книгу как подроб- ный справочник и сразу переходят к разделу, посвященному их люби- мой программе. Я не рекомендую так поступать.

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

Повесть, рассказанная в первых шести главах, формирует основу для прочтения остальных четырех глав, где описываются характерные особенности работы с регулярными выражениями в языках Perl, Java,

.NET и PHP. Я не скупился на перекрестные ссылки и постарался сде- лать алфавитный указатель максимально полезным.

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


Структура книги

Десять глав этой книги условно делятся на три логические части:

Вводная часть

В главе 1 представлены основные концепции регулярных выраже- ний.

В главе 2 рассматривается применение регулярных выражений при обработке текста.

В главе 3 приводится обзор диалектов регулярных выражений, а также некоторые исторические сведения.

Подробное описание

В главе 4 подробно рассмотрен механизм обработки регулярных выражений.


В главе 5 проанализированы некоторые последствия и практиче- ские применения материала главы 4.

В главе 6 обсуждаются проблемы эффективности.

Конкретные программы

В главе 7 подробно описан диалект регулярных выражений Perl.

В главе 8 рассматривается пакет java.util.regex для работы с регу- лярными выражениями в языке Java.

В главе 9 описан нейтральный по отношению к языкам пакет для работы с регулярными выражениями на платформе .NET.

В главе 10 рассматривается семейство функций preg, предназна- ченных для работы с регулярными выражениями в языке PHP.


Вводная часть

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

В результате основному тексту соответствует выражение ([ˆ/]|[ˆx]/)*, а всему комментарию – /x([ˆ/]|[ˆx]/)*x/.

К сожалению, это решение тоже не работает.

Начнем с /x([ˆx]|x[ˆ/])*x/. Рассмотрим строку ‘/ххFooxx/’ – после совпадения с ‘Foo’ первый символ x совпадает с x[ˆ/], что вполне нор-


мально. Но затем совпадает с xx/, а этот символ x должен входить в закрывающий ограничитель комментария. В результате совпадение продолжится и после x/ (до конца следующего комментария, если он существует).

Что касается /x([ˆ/]|[ˆx]/)*x/, то это выражение не совпадает с ‘/x/

years = days /x divide х//365; assume non–leap year x/

с подчеркнутым текстом (эта задача остается читателю для самостоя- тельной работы).

Работа над ошибками

Давайте попробуем исправить эти регулярные выражения. В первом выражении, где x[ˆ/] непреднамеренно совпадает с xx/ в завершении комментария, рассмотрим новый вариант /x([ˆx]|x+[ˆ/])*x/. Предпо- лагается, что благодаря дополнительному + x+[ˆ/] совпадает с цепоч- кой x, после которой следует символ, отличный от /. И это действитель-

но так, но из-за возврата «символ, отличный от /» может оказаться все тем же x. Сначала максимальный квантификатор x+ совпадает с лиш- ним x, как мы и хотели, но вследствие возврата этот символ может быть возвращен, если это необходимо для получения общего совпадения. К сожалению, выражение по-прежнему захватывает слишком много:

х А хх/ Foo() х В хх/

Чтобы прийти к правильному решению, нужно вспомнить то, что я го- ворил раньше: формулируйте выражение как можно точнее. Если мы хотим определить «цепочку x, после которой следует символ, отлич- ный от /», и при этом подразумевается, что «символ, отличный от /»,

также отличен и от x, об этом нужно сообщить явно: x+[ˆ/x]. Как и требовалось, эта запись предотвращает поглощение ‘xxx/’ – послед- него x в цепочке, завершающей комментарий. В качестве побочного

эффекта предотвращается совпадение со всеми символами x, заверша- ющими комментарий, поэтому мы оказываемся в позиции ‘xxx/’ пе- ред закрывающим ограничителем. Поскольку часть выражения, отно- сящаяся к завершающему ограничителю, допускает всего один сим- вол x, в нее необходимо добавить квантификатор +: x+/.

В результате получается следующее выражение: /x([ˆx]|x+[ˆ/x])*x+/.

Уф! Весьма запутанные рассуждения, не правда ли? Выражение для настоящих комментариев, со звездочками вместо x, выглядит еще ху- же: /\*([ˆ*]|\*+[ˆ/*])*\*+/. Чтобы прочитать такое выражение, вам придется изрядно пошевелить мозгами.



image

Перевод на язык регулярных выражений

На стр. 332, при описании двух вариантов поиска в комментари- ях С «всего, что не является закрывающим ограничителем», я представил две идеи:

«x, если за ним не следует символ /: x[ˆ/]»

и

«символом /, если ему не предшествует x: [ˆx]/»

При этом я выражался неформально – описания отличаются от приведенных регулярных выражений. Вы понимаете, о чем речь?

Чтобы разобраться, в чем заключаются отличия, примените пер- вое описание к строке ‘regex’. В ней присутствует символ x, за ко- торым не следует символ слэша, однако эта строка не совпадет с x[ˆ/]. Символьный класс совпадает с символом, и хотя этот символ не может быть косой чертой, он все равно должен быть чем-то другим, а не «ничем», как в строке ‘regex’. Во второй си- туации дело обстоит аналогично.

Если диалект поддерживает опережающую проверку, формули- ровка «x, если за ним не следует символ /» соответствует просто- му выражению x(?!/). Если опережающая проверка недоступна, попробуйте использовать выражение x([ˆ/]|$). Оно по-прежне- му совпадает с символом, следующим за x, но также может со- впадать и с концом строки. Если поддерживается ретроспектив- ная проверка, «символ /, которому не предшествует x», превра- щается в (?<!x)/. В противном случае то же самое можно сде- лать с помощью (ˆ|[ˆx])/.

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


Раскрутка выражения для поиска комментариев С

Попробуем повысить эффективность выражения, избавившись от кон- струкции выбора. В табл. 6.3 приведены выражения, которые должны подставляться в шаблон раскрутки цикла.

Как и в примере с доменными именами, норм* не может совпадать с «ничем». В предыдущем примере это было связано с тем, что «нор- мальная» часть (имя домена нижнего уровня) не могла быть пустой. В данном случае это объясняется особенностями обработки двухсим- вольного закрывающего ограничителя. Любая последовательность норм должна завершаться с первым символом закрывающего ограни- чителя, позволяя спец «перехватить» совпадение лишь в том случае, если следующий символ не завершает ограничитель.


Таблица 6.3. Компоненты раскрутки цикла для комментариев С

начало норм*(спец норм*)* конец


Компонент

Аналог в тексте

Регулярное выражение

начало

Начало комментария

/x

норм*

Текст комментария до одного или не- скольких x включительно

[ˆx]*x+

спец

Символ, отличный от символа обратно- го слэша (и не являющегося x)

[ˆ/x]

конец

Завершающий символ обратного слэша

/

Подставляя эти компоненты в общий шаблон раскрутки цикла, мы по- лучаем:

/x[ˆx]*x+( [ˆ/x][ˆx]*x+)*/

Обратите внимание на помеченный фрагмент. Механизм регулярных выражений может прийти к нему двумя путями (как и в выражении на стр. 326): либо продвижением через начальную конструкцию /x[ˆx]*x+, либо циклическим перебором ()*. В любом случае, оказавшись в этой позиции, мы знаем, что был найден символ x и текущая позиция явля-

ется критической точкой – возможно, в конце комментария. Если сле- дующим символом является символ слэша, поиск закончен. Если это любой другой символ (конечно, кроме x), мы знаем, что тревога была ложной и можно вернуться к поиску совпадений для компонента норм в ожидании следующего x. После того как символ будет найден, мы снова оказываемся в критической точке.

Практическая сторона

Выражение /x[ˆx]*x+([ˆ/x][ˆx]*x+)* не совсем готово к практическо- му использованию. Во-первых, конечно, комментарии обозначаются ограничителями /**/, а не /xx/. Проблема легко решается заменой каждого x на экранированную звездочку \* (в символьных классах – простой заменой x на *):

/\*[ˆ*]*\*+([ˆ/*][ˆ*]*\*+)*/

Также следует учесть тот факт, что комментарии часто распространя- ются на несколько строк. Если искомый текст содержит весь много- строчный комментарий, это выражение будет работать. Однако в строч- но-ориентированных программах (таких как egrep) не существует воз- можности применить регулярное выражение к полному коммента- рию. Но в большинстве программ, упомянутых в книге, это возможно, поэтому данное выражение может применяться, например, для удале- ния комментариев.

На практике возникает еще одна большая проблема. Наше регулярное выражение понимает комментарии С, но ничего не знает о других важ-


ных аспектах синтаксиса С. Например, оно может совпасть и при от- сутствии комментария:

const char *cstart = "/*". *cend = "*/";

Наше выражение будет усовершенствовано в следующем разделе.


Исключение случайных совпадений

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

$prog =~ s{/\*[ˆ*]*\*+(?:[ˆ/*][ˆ*]*\*+)*/}{}g; # удаление комментариев G

# (и не только!)

Фрагменты содержимого переменной $prog, соответствующие нашему регулярному выражению, заменяются «ничем» (т. е. удаляются). Проблема заключается в том, что в процессе перемещения начальной позиции начало совпадения может быть случайно обнаружено внутри строки, как в следующем фрагменте С:

char *GommentStart = "/*": /* Начало комментария */

char *GommentEnd = "*/"; /* Конец комментария */

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

Управление поиском совпадения

Рассмотрим следующий фрагмент:

$GOMMENT = qr{/\*[ˆ*]*\*+(?:[ˆ/*][ˆ*]*\*+)*/}; # Регулярное выражение

# для комментария

$DOUBLE = qr{"(?:\\.|[ˆ\\"])*"}; # Регулярное выражение # для строки в кавычках

$text =~ s/$DOUBLE|$GOMMENT//g;

Обратите внимание на два новых обстоятельства. Во-первых, регуляр- ное выражение-операнд $DOUBLE|$GOMMENT состоит из двух переменных, каждая из которых определяется при помощи оператора Perl qr//.


Как подробно обсуждалось в главе 3 ( 135), при создании строк, интер- претируемых как регулярные выражения, часто допускаются ошибки. Для решения этой проблемы в Perl был создан оператор qr//, который интерпретирует свой операнд как регулярное выражение, но не приме- няет его к тексту. Вместо этого он возвращает «объект регулярного вы-

ражения», который позднее может использоваться для построения больших регулярных выражений. В главе 2 ( 127) вы уже убедились, что этот оператор чрезвычайно удобен. Как и при использовании опера- торов m// и s///, ограничители можно выбирать по своему усмотре- нию ( 101); в данном примере были выбраны фигурные скобки.

Во-вторых, стоит обратить внимание на применение части $DOUBLE для поиска строк в кавычках. Когда в результате смещения механизм пе- реходит к позиции, в которой может совпасть компонент $DOUBLE, он назначает совпадение и обходит внутреннюю строку в кавычках. Воз- можность включения обеих альтернатив в поиск обусловлена полным отсутствием неоднозначности между ними. Начиная с левого края, любая начальная позиция в строке:


ку нулевая группа представляет все совпадение, промежуточные итерации отсутствуют, а коллекция состоит из одного объекта Gap– ture. Так как содержимое M.Gaptures и M.Group(0).Gaptures в точности соответствует содержимому нулевого объекта Group, эти конструк- ции особой пользы не приносят.

Объект Gapture – довольно любопытное новшество, которое выглядит более сложным и запутанным, чем на самом деле, из-за его «чрезмер- ной интеграции» в объектную модель. После того как я справился с до- кументацией .NET и понял, как работают эти объекты, я отношусь к ним со смешанными чувствами. С одной стороны, новинка безуслов- но интересная. Я не берусь сходу предложить практическое примене- ние для объектов Gapture, но это, вероятно, объясняется тем, что мой опыт работы с ними еще недостаточен.

С другой стороны, все эти дополнительные группы конструируются в процессе поиска, а их инкапсуляция в объектах после поиска приво- дит к снижению эффективности; мне бы не хотелось платить такую це- ну, если дополнительная информация не используется в программе. В абсолютном большинстве программ группы Gapture не используют- ся, но, несмотря на это, все объекты Group и Gapture (а также ассоцииро- ванные с ними объекты GroupGollection и GaptureGollection) все равно строятся при создании объекта Match. Таким образом, вы получаете эти объекты независимо от того, нужны они вам или нет. Впрочем, если вы придумаете достойное практическое применение для объектов Gap– ture – используйте их.


10

PHP


Со второй половины 90-х годов, в период этапа бурного развития Веб, известного как «Web boom», язык PHP переживает период оглуши- тельной популярности, рост которой продолжается и по сей день. Одна из причин такой популярности заключается в том, что даже неспеци- алисты после некоторой подготовки имеют возможность использовать основные его возможности. К тому же, несмотря на такую доступ- ность, язык PHP обеспечивает широчайший круг функциональных возможностей, которые, вне всякого сомнения, придутся по душе да- же бывалому программисту. Разумеется, PHP обладает поддержкой регулярных выражений, причем поддержка эта реализована в виде не менее трех механизмов регулярных выражений, никак не связанных друг с другом.

PHP включает в себя механизмы «preg», «ereg» и «mb_ereg». В этой книге будет рассматриваться семейство функций preg. В основе этого семейства лежит механизм НКА, а по своим возможностям и по произ- водительности функции этого семейства опережают два других. (Сло- во «preg» следует произносить как «пи-рег».)

О предыдущих главах

Прежде чем представлять читателю содержимое этой главы, я должен подчеркнуть, что она в значительной степени основана на материале глав 1–6. Я понимаю, что некоторые читатели, программирующие только на языке PHP, могут начать сразу с этой главы, но я рекомен- дую ознакомиться с предисловием (особенно с системой условных обозначений) и предыдущими главами. В главах 1, 2 и 3 представлены многие концепции, возможности и приемы, используемые при работе с регулярными выражениями, а материал глав 4, 5 и 6 представляет ключевую информацию для понимания регулярных выражений, ко- торая напрямую относится к механизму preg регулярных выражений


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

Здесь мне хочется заметить, что, несмотря на наличие удобных таблиц, таких как на стр. 522 в этой главе или на стр. 149 и 160 в главе 3, дан- ная книга не претендует на роль справочного руководства. Главная ее цель – научить вас искусству составления регулярных выражений.

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

История развития механизма preg

Название «preg» происходит от префикса preg, с которого начинаются имена всех функций, составляющих интерфейс к этому механизму, и означает: «Perl Regular Expressions» (регулярные выражения Perl). Этот механизм был добавлен Андреем Змиевски (Andrei Zmievski), ко- торого не устраивали ограничения, присущие стандартному на то время механизму ereg. (Название «ereg» расшифровывается как «extended re- gular expressions», т. е. «расширенные регулярные выражения» – PO- SIX-совместимый пакет, обладающий «расширенными» возможнос- тями по сравнению с большинством обычных диалектов, однако с вы- соты современных стандартов он выглядит крайне минималистским.)

Андреем было добавлено семейство функций preg, которые составили интерфейс к PCRE («Perl Compatible Regular Expressions» – регуляр- ные выражения, совместимые с Perl) – замечательной библиотеке под- держки регулярных выражений на базе механизма НКА, которая очень близко имитирует синтаксис и семантику регулярных выраже- ний языка Perl и обеспечивает мощь, которой так не хватало Андрею.

Прежде чем наткнуться на библиотеку PCRE, Андрей взялся за изуче- ние исходных текстов Perl, чтобы понять, что можно было бы позаим- ствовать для использования в PHP. Вне всяких сомнений он был дале- ко не первым, кто взялся за это и, конечно же, не первым, кто быстро пришел к выводу, что дело это не для слабонервных. Исходные тексты Perl, регулярные выражения которого поражают своей мощью и ско- ростью исполнения, за долгие годы неоднократно переделывались многими людьми и со временем превратились в нечто, выходящее за рамки понимания обычного человека.

К счастью, в свое время Филип Хейзель (Philip Hazel) из Кембридж- ского университета в Англии, также пораженный исходными текста- ми механизма регулярных выражений Perl, создал библиотеку PCRE (ссылка на которую приводилась в главе 3 на стр. 123). Филип начал


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

На протяжении многих лет в соответствии с изменениями в Perl продол- жала свое развитие и библиотека PCRE, а вместе с ней и PHP. В этой книге рассматриваются версии PHP 4.4.3 и 5.1.4. Обе эти версии включают в себя PCRE версии 6.6.1

Для тех, кто еще не знаком с порядком нумерации версий PHP, заме- чу, что параллельно продолжают развиваться ветки 4.x и 5.x, при том что PHP версий 5.x был во многом переписан заново. Так как разработ- ка и выпуск новых версий PHP в обеих ветках происходят независимо друг от друга, вполне возможна ситуация, когда версия PHP из ветки

5.x будет содержать более старую версию PCRE, чем более свежий вы- пуск PHP из ветки 4.x.


Диалект регулярных выражений PHP

В табл. 10.1 приводятся краткие сведения о диалекте регулярных выра- жений preg. Ниже приводятся дополнительные замечания к табл. 10.1:

\b представляет символ backspace (забой) только в символьных классах; за их пределами он представляет границу слова ( 174).

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

\0, состоящая из одной цифры, соответствует символу NUL.

Метапоследовательность \xшестн может состоять из одной или двух цифр. Синтаксис \x{шестн} позволяет задавать шестнадца- теричные коды произвольной длины. Однако значения больше

\x{FF} считаются допустимыми только при наличии модификатора u ( 528). Без этого модификатора использование значений больше чем \x{FF} будет расцениваться как ошибка.

Даже в режиме использования кодировки UTF-8 (с модификатором u) метасимволы границ слов и символьные классы, такие как \w, работают только с ASCII-символами. В случае необходимости рабо- тать с полным диапазоном символов Юникода вместо \w следует пользоваться конструкцией \pL ( 159), вместо \d – конструкци- ей \pN, а вместо \s – конструкцией \pz.


image

1 Занявшись исследованием различных версий PHP и PCRE, доступных к моменту написания этой главы, я обнаружил несколько ошибок, которые были исправлены в версиях PHP 4.4.3 и 5.1.4 (рассматриваемых в этой книге). Некоторые примеры из этой главы могут не работать с более ранни- ми версиями.


Таблица 10.1. Общие сведения о диалекте preg регулярных выражений PHP

image

151 (C) \а [\b] \e \t \n \r \t \восьм \xшестн \x{шестн} \cсимвол

Сокращенные обозначения символов

Символьные классы и аналогичные конструкции

image

155 Обычные классы: [] и [^] (допускаются конструкции стандарта POSIX [:alpha:] 166)

156 Любой символ, кроме символа новой строки: точка (с модифика- тором s – любой символ)

157 (U) Комбинационные последовательности Юникода:

158 (C) Сокращенные обозначения классов: \w \d \s \W \D \S (только для 8- битных символов)

159 (C) Свойства, алфавиты и блоки Юникода: \p{свойство},


157

(U) \P{свойство}

Принудительное однобайтовое совпадение (может быть рискован- ным):\C

Якорные метасимволы и другие проверки с нулевой длиной совпадения

image

169 Начало строки/логической строки: ^ \A

169 Конец строки/логической строки:$ \Z \z

171 Начало текущего совпадения: \G

174 Границы слов: \b \B (только для 8-битных символов)

175 Позиционная проверка: (?=) (?!) (?<=) (?<!)

Комментарии и модификаторы режимов

image

527 Модификаторы режимов: (?мод(мод). Допустимые модификаторы:

х s m i X U

527 Интервальное изменение режима: (?мод(мод:)

177 Комментарии: (?#) (с модификатором x, а также от символа # до новой строки или конца регулярного выражения)

Группировка, сохранение, условные и управляющие конструкции

image

178 Сохраняющие круглые скобки: () \1 \2 ...

180 Именованное сохранение: (?P<имя>) (?P=имя)

178 Группирующие круглые скобки: (?:)

180 Атомарная группировка: (?>)

181 Конструкция выбора: |

563 Рекурсия: (?R) (?число) (?P>имя)

182 Условная конструкция: (?if then|else) – в части if может нахо- диться позиционная проверка, (R) или (число)

183 Максимальные квантификаторы: * + ? {n} {n,} {min, max}

184 Минимальные квантификаторы: *? +? ?? {n}? {n,}? {min, max}?


Сокращенные обозначения символов

184

177 (C)

Захватывающие квантификаторы: *+ ++ ?+ {n}+ {n,}+ {min, max}+

Литеральный текст: \Q \E

(C) – может использоваться в символьном классе

(U) – только при совместном использовании с модификатором u 528

– дополнительные замечания приводятся в тексте

(Эта таблица может также служить описанием библиотеки PCRE, составляю- щей фундамент для функций семейства preg 123.)


PHP ориентируется на стандарт Юникода версии 4.1.0.

Поддержка алфавитов Юникода реализована без использования префиксов ‘Is’ или ‘In’, например: \p{Gyrillic} ( 159).

Поддерживаются одно- и двухсимвольные сокращенные имена свойств, такие как \p{Lu}, \p{L} и \pL ( 159). Длинные конструк- ции вида \p{Letter} не поддерживаются.

По умолчанию регулярные выражения механизма preg ориентиро- ваны на работу с однобайтовыми символами, а метасимвол \G по умолчанию означает то же, что и конструкция (?s:.) s-модифи- кация метасимвола .. Однако, при наличии модификатора u, регу- лярные выражения механизма preg в состоянии работать с символа- ми в кодировке UTF-8, т. е. с композитными символами, имеющим размер до 6 байтов. Но даже в этом случае \G продолжает соответст- вовать единственному байту. Предупреждение об этой особенности приводится на стр. 157.

Оба метасимвола \z и \z могут совпадать с самым концом целевой строки, но \z может также соответствовать заключительному сим- волу новой строки.

Смысл метасимвола $ зависит от наличия модификаторов m и D ( 527): в отсутствие модификаторов \$ является аналогом \z (со- впадение обнаруживается либо перед заключительным символом новой строки, либо в самом конце целевой строки); с модификато- ром m он также может совпадать с промежуточными символами но- вой строки; с модификатором D является аналогом \z (соответствие обнаруживается только в конце строки). При наличии обоих моди- фикаторов, m и D, модификатор D игнорируется.

Ретроспективная проверка ограничивается подвыражениями, со- впадающими с текстом фиксированной длины, при этом на верх- нем уровне допускаются альтернативы различной фиксированной длины ( 174).

Модификатор x (режим свободного форматирования и комментари- ев) распознает только пропуски из набора ASCII. Остальные симво- лы пропусков Юникода не распознаются.


Функциональный интерфейс механизма preg

Для доступа к механизму регулярных выражений язык PHP предо- ставляет исключительно процедурный интерфейс ( 127), который со- стоит из семи функций, перечисленных в верхней половине табл. 10.2. Кроме того, в таблице перечислены четыре дополнительные полезные функции, исходные тексты которых будут представлены ниже в этой же главе.

Таблица 10.2. Перечень функций языка PHP для доступа к механизму регулярных выражений Preg


Функция

Назначение

531 preg_match

Проверяет наличие совпадений в строке и извлекает данные из строки

536 preg_match_all

Извлекает данные из строки

542 preg_replace

Замещает найденное совпадение копией задан- ной строки

548 preg_replace_callback

Для каждого найденного совпадения вызывает заданную функцию

551 preg_split

Разбивает исходную строку на массив подстрок

556 preg_grep

Отбирает элементы массива, которые соот- ветствуют/не соответствуют заданному регу- лярному выражению

557 preg_quote

Экранирует метасимволы регулярных выраже- ний в строке

Следующие функции будут разработаны в этой главе; сюда они включены для удобства поиска.

image

538 reg_match Версия preg_match, которая различает круглые скобки, не участвовавшие в совпадении

558 preg_regex_to_pattern Создает строку шаблона preg из строки регу-

лярного выражения

562 preg_pattern_error Проверяет строку шаблона preg на наличие

синтаксических ошибок

562 preg_regex_error Проверяет строку регулярного выражения на

наличие синтаксических ошибок


Результат работы каждой из этих функций во многом зависит от коли- чества и типов входных аргументов, флагов и модификаторов, исполь- зуемых в регулярном выражении. Прежде чем приступить к подроб- ному обсуждению, рассмотрим несколько примеров, чтобы получить некоторое представление о том, как выглядят и как обрабатываются регулярные выражения в PHP:

/* Проверяет, является ли тег HTML тегом <table> */ iF (preg_match('/^<table\b/i', $tag))


print "tag is a table tag\n";


image

/* Проверяет, является ли строка изображением целого числа */ iF (preg_match('/^-?\d+$/', $user_input))

print "user input is an integer\n";


image

/* Извлекает из строки содержимое HTML–тега <title> */

iF (preg_match('{<title>(.*?)</title>}si', $html, $matches)) print "page title: $matches[1]\n";


image

/* Интерпретирует числа в строке, как значения температуры по Фаренгейту и замещает их значениями температуры по Цельсию */

$metric = preg_replace('/(-?\d+(?:\.\d+)?)/e', /* шаблон */ 'Floor(($1–32)*5/9 + 0.5)', /* код, выполняющий замену */

$string);


image

/* Создает массив значений, полученных из строки в формате GSV */

$values_array = preg_split('!\s*,\s*!', $comma_separated_values);

В последнем примере, когда заданная строка содержит текст ‘Lar– ry,Gurly,Moe’, в результате будет получен массив из трех строк: ‘Lar– ry’, ‘Gurly’ и ‘Moe’.

Аргумент «шаблон»

Первым аргументом любой функции из семейства preg передается шаблон, представляющий собой регулярное выражение, окруженное парой разделителей, за которым могут следовать модификаторы шаб- лона. В первом примере выше шаблоном является строка '/<table\b/i', которая представляет регулярное выражение <table\b, окруженное двумя символами слэша (разделителями), за которым следует моди- фикатор шаблона i (поиск без учета регистра символов).

Строки в апострофах в языке PHP

В регулярных выражениях очень часто используются символы обрат- ного слэша, поэтому наиболее удобной формой представления шабло- нов в PHP являются строки литералов в апострофах. Строки литера- лов уже рассматривались в главе 3 ( 137), однако в двух словах на- помню, что при использовании строк в апострофах вам не придется до- бавлять массу дополнительных экранирующих символов обратного слэша для представления регулярного выражения в тексте програм- мы. В языке PHP специальной интерпретации подвергаются всего две метапоследовательности, которые могут встречаться в строках, за- ключенных в апострофы. Это ‘\'’ и ‘\\’, которые позволяют включать в строки символы ‘'’ и ‘\’ соответственно.

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


ния каждого \ необходимо указывать \\, поэтому, чтобы представить

\\, необходимо записать \\\\. И все это для того, чтобы найти совпаде- ние с единственным символом обратного слэша!

(Пример подобного гипертрофированного использования символов об- ратного слэша вы найдете на стр. 560.)

В качестве конкретного примера рассмотрим регулярное выражение, которое находит совпадение с именем диска в операционной системе Windows, например ‘G:\’. Само регулярное выражение выглядит сле- дующим образом: ˆ[A–z]:\\$, однако после заключения в апострофы оно уже будет выглядеть так: 'ˆ[A–z]:\\\\$'.

В примере на стр. 240 (глава 5) мы уже видели, что для представления выражения ˆ.*\\ используется строка '/ˆ.*\\\/' – с тремя символами обратного слэша. Помня об этом, я посчитал, что следующие примеры будут весьма поучительными:

print '/ˆ.*\/'; выведет: /ˆ.*\/ print '/ˆ.*\\/'; выведет: /ˆ.*\/ print '/ˆ.*\\\/'; выведет: /ˆ.*\\/ print '/ˆ.*\\\\/'; выведет: /ˆ.*\\/

Первые два примера дают одинаковые результаты, хотя достигается это разными способами. В первом случае последовательность ‘\/’, за- вершающая строку, не имеет специального значения в строках, за- ключенных в апострофы, поэтому данная последовательность выводит- ся как последовательность литералов. Во втором случае последователь- ность ‘\\’ имеет специальную интерпретацию в строковых литералах и представляет одиночный символ ‘\’. Таким образом, в комбинации с завершающим символом слэша результат получается тем же самым, что и в случае с комбинацией ‘\/’, которая используется в первом при- мере. Следуя той же логике, несложно понять, почему третий и чет- вертый примеры дают одинаковые результаты.

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

Разделители

Механизм preg требует наличия разделителей, окружающих регуляр- ные выражения, потому что разработчики стремились обеспечить бо- лее близкую к Perl имитацию регулярных выражений, особенно при использовании модификаторов. Для некоторых программистов это об- стоятельство может показаться осложняющим фактором, в сравнении с возможностью передачи модификаторов каким-либо иным способом, но как бы то ни было, мы имеем то, что мы имеем. (Один из «худших» примеров вы найдете во врезке на стр. 530.)

Наиболее часто в качестве разделителя используют символ слэша, од- нако можно употреблять любые не алфавитно-цифровые символы,


за исключением пробела ASCII и символа обратного слэша. Помимо символа слэша в качестве разделителей нередко встречаются символы ‘!’ и ‘#’.

Если в качестве первого разделителя используется один из «открываю- щих» знаков пунктуации:

{ ( < [

то в качестве завершающего разделителя должен использоваться пар- ный «закрывающий» знак пунктуации:

} ) > ]

При использовании таких «парных» разделителей их можно приме- нять для построения вложенных конструкций, т. е. в качестве строки шаблона вполне допустимо использовать такую комбинацию: '((\d+))'. В данном примере внешние скобки являются разделителями, ограни- чивающими шаблон, а внутренние скобки являются частью регуляр- ного выражения. Однако во избежание путаницы я рекомендовал бы использовать более простую форму: '/(\d+)/'.

Символы, используемые в качестве разделителей, внутри строк шаб- лонов регулярных выражений необходимо экранировать. Так, запись вида '/<B>(.*?)<\/B>/i' считается допустимой, хотя в подобной ситуа- ции удобнее было бы использовать запись '!<B>(.*?)</B>!i', где в каче- стве разделителей выступают символы ‘!!’, или '{<B>(.*?)</B>}i', где используются разделители ‘{}’.

Модификаторы шаблонов

image

Модифи- Встроенный Описание катор модификатор

i (?i)

m (?m)

s

x u

(?s)

(?x)

X

(?X)

145 Поиск совпадений без учета регистра символов

147 Расширенный режим привязки к границам строк

146 Режим совпадения точки со всеми символами

146 Режим свободного форматирования

528 Регулярное выражение и целевая строка ин- терпретируются как строки символов Юникода

528 Разрешает использование дополнительных возможностей PCRE

После закрывающего разделителя, а в некоторых случаях и внутри ре- гулярного выражения, для настройки определенных аспектов исполь- зования шаблонов могут помещаться различные модификаторы режи- ма (в терминологии PHP именуемые модификаторами шаблонов). В приведенных выше примерах нам уже встречался модификатор шаблона i, включающий режим поиска без учета регистра символов. Ниже приводится перечень всех допустимых модификаторов:



image

Модифи- Встроенный Описание катор модификатор

e

S

543 Строка замены интерпретируется как прог-

раммный код PHP (только для функции preg_replace)

567 Запускает попытку оптимизации регулярного выражения («study»)

Следующие модификаторы используются достаточно редко


U

(?U)

528 Изменяет степень максимализма на противо-



положную для * и *?, и других

A


528 Привязывает все совпадение к начальной по- зиции поиска

D


528 $ совпадает с концом строки (EOS), но не с заключительным символом новой сроки. (Игнори- руется при использовании модификатора m.)


Модификаторы шаблонов внутри регулярных выражений

Внутри регулярных выражений модификаторы шаблонов могут ис- пользоваться для временного включения или выключения режимов поиска (например, (?i) включает режим поиска без учета регистра символов, а (?–i) – выключает его 176). При таком использовании оказываемый модификатором эффект распространяется до конца объ- емлющих круглых скобок, если таковые имеются, либо до конца регу- лярного выражения.

Они могут использоваться также как интервальные модификаторы ре( жима ( 177), например конструкция (?i:) включает режим поиска без учета регистра символов, а конструкция (?–sm:) отключает дейст-

вие модификаторов s и m для заданного участка регулярного выражения.

Модификаторы режимов за пределами регулярных выражений

После заключительного разделителя модификаторы могут комбини- роваться в любом порядке, например: ‘si’ – эта комбинация включает режимы поиска без учета регистра символов и совпадения точки со всеми символами:

iF (preg_match('{<title>(.*?)</title>}si', $html, $captures))


Модификаторы, специфичные для PHP

Первые четыре модификатора из таблицы выше являются стандарт- ными и уже обсуждались в главе 3 ( 145). Модификатор шаблона e используется исключительно вместе с функцией preg_replace и будет описан в этом разделе ( 543).

Модификатор шаблона u сообщает механизму регулярных выраже- ний, что само регулярное выражение и целевая строка содержат сим- волы в кодировке UTF-8. Наличие этого модификатора не приводит


к изменению байтов, он просто воздействует на способ их интерпрета- ции. По умолчанию (т. е. без модификатора u), механизм preg рас- сматривает полученные им данные как 8-битовые символы текущего локального контекста ( 119). Применяйте модификатор u, только если заранее известно, что данные будут содержать символы в коди- ровке UTF-8, в противном случае использовать этот модификатор не следует. Символы в кодировке UTF-8, коды которых не совпадают с кодами ASCII, кодируются несколькими байтами, и использование модификатора u гарантирует, что такие многобайтовые последова- тельности будут интерпретироваться как одиночные символы.

Модификатор шаблона X включает использование «дополнительных возможностей» PCRE, но пока из них доступна только одна: генерация ошибки в случае использования в регулярном выражении символа об- ратного слэша, когда он не является частью известного метасимвола. Например, по умолчанию метасимвол \k не имеет специального зна- чения в PCRE, и он интерпретируется как k (так как обратный слэш не является частью известной метапоследовательности, он просто иг- норируется). Использование модификатора X в подобной ситуации приведет к фатальной ошибке «unrecognized character follows \» (не- известный символ после \).

Вполне возможно, будущие версии PHP будут включать в себя версии библиотеки PCRE, в которых неизвестные ныне метасимволы будут интерпретироваться особым образом. Поэтому с целью обеспечения со- вместимости с будущими версиями (и удобочитаемости) лучше отка- заться от использования экранированных символов, которые не име- ют специального назначения. В этом случае модификатор X приобре- тает особую значимость, так как с его помощью без труда можно опре- делить места опечаток.

Модификатор шаблона S запускает механизм «study» библиотеки PCRE, который выполняет предварительный анализ регулярного выражения, что в некоторых четко определенных ситуациях позволяет незначи- тельно ускорить поиск совпадений. Подробнее об этом модификаторе будет рассказываться в разделе, посвященном вопросам повышения эффективности, который начинается со стр. 566.

Остальные модификаторы шаблонов являются довольно экзотически- ми и используются достаточно редко:

Предложение по применению

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


Расширенные примеры

Ниже приводятся два примера, завершающие главу.

Разбор данных в формате CVS в PHP

Ниже приводится PHP-версия примера разбора данных в формате CSV (данных, разделенных запятыми) из главы 6 ( 330). Регулярное вы- ражение было дополнено использованием захватывающих квантифи- каторов ( 184) вместо атомарной группировки, что обеспечило более ясное его представление.

Сначала идет регулярное выражение:

$csv_regex = '{

\G(?:ˆ|,) (?:

# Поле в кавычках...

" # открывающая кавычка

( [ˆ"]*+ (?: "" [ˆ"]*+ )*+ )

" # закрывающая кавычка

| # ...или...

# ...произвольный текст, кроме кавычек и запятых... ( [ˆ",]*+ )

)

}x';

А затем реализация разбора текста в формате CSV, который содержит- ся в переменной $line:

/* Применить регулярное выражение, заполнить $all_matches всеми типами данных

*/

preg_match_all($csv_regex, $line, $all_matches);

/* В $Result будут храниться поля, которые мы извлечем из $all_matches */


$Result = array ();

/* Обойти все успешные совпадения... */

For ($i = 0; $i < count($all_matches[0]); $i++)

{

/* Если это совпадение со второй парой сохраняющих скобок – использовать

* значение как есть */

iF (strlen($all_matches[2][$i]) > 0) array_push($Result, $all_matches[2][$i]);

else

{

/* Если это значение в кавычках, предварительно заменить

* последовательности из двух кавычек одной кавычкой */ array_push($Result, preg_replace('/""/', '"', $all_matches[1][$i]));

}

}

/* Теперь массив $Result заполнен и готов к дальнейшему использованию */


Проверка тегированных данных

на корректность вложенных конструкций

Следующий далее пример содержит в себе массу интересных момен- тов: он выполняет проверку данных в формате XML (XHTML или лю- бых других тегированных данных) на отсутствие непарных или неза- крытых тегов. При построении регулярного выражения я отталкивал- ся от следующих положений: каждому открывающему тегу должен соответствовать парный закрывающий тег, данные могут содержать текст вне тегов и могут существовать самозакрывающиеся теги (на- пример, <br/> – «теги без вложенных элементов» в языке XML), при условии, что поиск ведется по всей строке.

Ниже приводится полное регулярное выражение:

ˆ((?:<(\w++)[ˆ>]*+(?<!/)>(?1)</\2>|[ˆ<>]++|<\w[ˆ>]*+/>)*+)$

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

Выражение может показаться достаточно сложным, но после разделе- ния на отдельные компоненты сопровождать его становится достаточ- но просто. Тело регулярного выражения окружено конструкцией

ˆ()$, чтобы гарантировать, что вся строка целевого текста участвует в совпадении. Основное тело выражения также окружено дополни-

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

Основное тело выражения

Основное тело выражения содержит три альтернативы (каждая из ко- торых выделена подчеркиванием для большей ясности), заключенных в конструкцию (?:)*+, что допускает совпадение с ними в любой ком-


бинации. Первая альтернатива соответствует парным тегам, вторая – тексту вне тегов и третья – самозакрывающимся тегам.

Совпадение с любой из альтернатив является уникальным по отноше- нию к другим альтернативам (т. е. если текст совпадает с одной альтер- нативой, он не будет совпадать ни с одной из других альтернатив). Зная, что последующий возврат не приведет к совпадению того же са- мого текста с другой альтернативой, можно взять этот факт на воору- жение и повысить эффективность регулярного выражения за счет при- менения захватывающего квантификатора * к скобкам, «допускающим совпадения в любой комбинации». Благодаря этому механизм регуляр- ных выражений даже не будет пытаться выполнить возврат, что уско- рит достижение результата, когда совпадение не может быть найдено.

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

Теперь рассмотрим каждую из альтернатив по отдельности...

Вторая альтернатива: текст вне тегов

Начнем со второй альтернативы, как с наиболее простой: [ˆ<>]++. Этой альтернативе соответствует текст, расположенный вне тегов. Ис- пользование захватывающего квантификатора здесь может показать- ся избыточным, если учесть, что объемлющая конструкция (?:)*+

также снабжена захватывающим квантификатором. Я предпочитаю использовать захватывающие квантификаторы, если знаю, что это не повредит. (Захватывающие квантификаторы часто используются из соображений эффективности, но при этом они изменяют семантику поиска совпадения. Такое изменение может быть полезным, но вы должны понимать его суть 317.)

Третья альтернатива: самозакрывающиеся теги

Третьей альтернативе, <\w[ˆ>]*+/>, соответствуют самозакрывающие- ся теги, такие как <br/> и <img /> (самозакрывающиеся теги отличает символ ‘/’, вслед за которым сразу же следует закрывающая угловая

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

Первая альтернатива: совпадение с парой тегов

Наконец мы подошли к рассмотрению первой альтернативы: <(\w++) [ˆ>]*+(?<!/)>(?1)</\2>.

Первая часть выражения (выделена подчеркиванием) соответствует открывающему тегу: конструкция (\w++) сохраняет имя тега и явля- ется второй парой сохраняющих круглых скобок всего выражения. (Использование захватывающего квантификатора в (\w++) – очень важный момент, на котором мы вскоре остановимся отдельно.)


Конструкция (?<!/) – это негативная ретроспективная проверка ( 175), которая гарантирует отсутствие символа ‘/’ перед только что найденным совпадением. Эта конструкция была помещена в разделе

«совпадение с открывающим тегом» непосредственно перед >, чтобы убедиться, что это не самозакрывающийся тег, такой как <hr/> (само- закрывающиеся теги обслуживаются третьей альтернативой, которую мы уже рассмотрели).

После того как будет найдено совпадение с открывающим тегом, вы- полняется (?1) – рекурсивное применение подвыражения в первой па- ре сохраняющих круглых скобок. Это и есть вышеупомянутое «основ- ное тело», которому соответствует фрагмент текста без непарных тегов. Как только это совпадение будет обнаружено, мы должны оказаться в закрывающем теге, парном открывающему тегу, найденному в пер- вой части альтернативы (имя которого было сохранено во второй паре сохраняющих скобок). Начальные символы </ в подвыражении </\2> гарантируют, что мы имеем дело с закрывающим тегом, а обратная ссылка \2 – что мы имеем дело с корректным закрывающим тегом.

Если вы предполагаете использовать это выражение для проверки HTML или других данных, где регистр символов в именах тегов не имеет значения, добавьте в начало регулярного выражения конструк- цию (?i) или используйте модификатор шаблона i.

Все!


Захватывающие квантификаторы

Мне хотелось бы дополнительно прокомментировать использование захватывающего квантификатора \w++ в первой альтернативе <(\w++) [ˆ>]*+(?<!/)>. Если бы мне пришлось использовать диалект регулярных выражений с меньшими выразительными возможностями, в котором отсутствуют захватывающие квантификаторы или атомарная группи- ровка ( 180), я использовал бы в этой альтернативе \b после (\w+), чтобы обеспечить совпадение с именем тега: <(\w+)\b[ˆ>]*(?<!/)>.

Метасимвол \b позволит, к примеру, предотвратить совпадение на- чальных символов ‘li’ в последовательности «<link></li>». Без него выражение оставило бы ‘nk’ для совпадения за пределами сохраняю- щих скобок, и как следствие – усеченное имя тега для обратной ссыл- ки \2, которая следует далее.

Обычно такого не происходит, так как \w+ является максимальным и старается обеспечить соответствие полному имени тега. Однако если это регулярное выражение применить к тексту с неправильной вло- женностью, для которого не должно быть совпадения, то возврат в процессе поиска совпадения может вынудить \w+ вернуть часть сим- волов и тем самым дать совпадение с неполным именем тега, как

в примере с тегами ‘<link></li>’. Метасимвол \b предотвращает та- кую возможность.


К счастью, мощный механизм preg в PHP поддерживает захватываю- щие квантификаторы, а использование такого квантификатора в кон- струкции \w++ означает «не допускать разделение имени тега в ре- зультате возврата», поэтому достигается эффект использования \b, при этом более эффективно.


Настоящий XML

Формат XML имеет более сложную структуру, которую нельзя выра- зить простой концепцией парных тегов. Кроме всего прочего необхо- димо также учитывать комментарии XML, секции CDATA и инструк- ции обработки.

Добавление поддержки комментариев XML выражается в добавлении четвертой альтернативы <!––.*?––> и использовании (?s) или моди- фикатора шаблона s, чтобы обеспечить совпадение точки с символом новой строки.

Аналогично секции CDATA, которые имеют форму <![GDATA[]]>, мо- гут обслуживаться еще одной альтернативой <!\[GDATA\[.*?]]>, а ин( струкции обработки XML, такие как ‘<?xmlversion="1.0"?>’, могут об- служиваться с помощью альтернативы <\?.*?\?>.

Объявления сущностей, которые имеют вид <!ENTITY>, можно обрабо- тать с помощью альтернативы <!ENTITY\b.*?>. В языке XML существу- ет еще ряд аналогичных структур, обработка которых может быть объ- единена путем замены <!ENTITY\b.*?> на <![A–z].*?>.

Некоторые проблемы остаются, но того, что мы уже обсудили, вполне должно хватить для работы с большинством XML-документов. Ниже приводится фрагмент, в котором учтены все сделанные замечания:

$xmlRregex = '{

ˆ(

(?: <(\w++) [ˆ>]*+ (?<!/)> (?1) </\2> # соответствует парным тегам

|[ˆ<>]++ # текст вне тегов

| <\w[ˆ>]*+/> # самозакрывающиеся теги

| <!––.*?––> # комментарии

| <!\[GDATA\[.*?]]> # блоки cdata

| <\?.*?\?> # инструкции обработки

| <![A–z].*?> # объявления сущностей и пр.

)*+

)$

}sx';


iF (preg_match($xml_regex, $xml_string)) echo "block structure seems valid\n";

else

echo "block structure seems invalid\n";


HTML?

В HTML-документах наиболее часто встречаются все виды проблем, которые делают нецелесообразной проверку, подобную этой: среди них непарные и незакрытые теги, неправильное использование симво- лов ‘<’ и ‘>’. Однако даже в правильно оформленных HTML-докумен- тах имеются специальные случаи, которые требуют дополнительной обработки, – это комментарии и теги <script>.

Комментарии HTML обрабатываются аналогично комментариям XML – с помощью конструкции <!––.*?––> и модификатора шаблона s.

Секция <script> требует особого внимания, потому что в ее пределах до- пускается использовать символы ‘<’ и ‘>’, следовательно, нам необхо- димо разрешить появление любых символов и их последовательностей между открывающим тегом <script> и закрывающим тегом </script>. Сделать это можно с помощью выражения <script\b[ˆ>]*>.*?</script>. Интересно, что если секция сценария не содержит запрещенных сим- волов ‘<‘ и ‘>’, она будет соответствовать первой альтернативе, потому что соответствует «совпадению с парой тегов». Если <script> будет со- держать такие символы, первая альтернатива потерпит неудачу, оста- вив последовательность для совпадения с этой альтернативой.

Ниже приводится версия фрагмента программного кода PHP для про- верки HTML:

$htmlRregex = '{

ˆ(

(?: <(\w++) [ˆ>]*+ (?<!/)> (?1) </\2> # соответствует парным тегам

|[ˆ<>]++ # текст вне тегов

| <\w[ˆ>]*+/> # самозакрывающиеся теги

| <!––.*?––> # комментарии

| <script\b[ˆ>]*>.*?</script> # блоки сценариев

)*+

)$

}isx';

iF (preg_match($html_regex, $html_string)) echo "block structure seems valid\n";

else

echo "block structure seems invalid\n";


Алфавитный указатель


Специальные символы

\0, 153

\1, 366

Perl, 67

?

введение, 42

и возврат, 206

?!, 329

?…?, 372

(?i), 528

(?i), 527

(?m), 527

(?s), 527

(?U), 528

(?X), 527

(?x), 527

(?!), 399, 401

(?#…), 150, 177

(?1), 564

Java, 477

PCRE, 564

PHP, 564, 572

(?n), 484

(?P<…>), 535

(?R)

PCRE, 563

PHP, 563

\(…\), 178

//, 387

\ \ \ \, 240 @

интерполяция переменных, Perl, 351 экранирование, 107

@, 363, 365

@+, 363, 365

@"…", 137

., метасимвол Java, 442

=~, введение, 65

*

введение, 43

и возврат, 207

.*

введение, 84

механика поиска совпадений, 196 оптимизация, 302

+

введение, 43

и возврат, 207

++, 572

\+, история, 119

\<…\>, 47, 78, 174, 193

egrep, 39

Emacs, 135

<>, 83

[:<:], 124

[=…=], 168

[:…:], 166

[…..], 167

[:>:], 124

$, 148, 529

Java

метасимвол, 442

якорный метасимвол, 169 Perl

интерполяция переменных, 350,

351

обозначение переменных в, 63 PHP, 523

экранирование, 107

$$, .NET, 502

\$, PHP, 523

$/, 61

$&, переменная, 362, 363

.NET, 502

для нужд отладки, 398 имитация, 427

недостатки, 426


предварительное копирование, 425 проверка на наличие в программе, 428

$', переменная, 362, 363

.NET, 502

для нужд отладки, 398 имитация, 427

недостатки, 426

предварительное копирование, 425 проверка на наличие в программе, 428

$`, переменная, 362, 363

.NET, 502

для нужд отладки, 398 имитация, 427

недостатки, 426

предварительное копирование, 425 проверка на наличие в программе, 428

$+, переменная, 363, 364, 413

.NET, 254, 502

предварительное копирование, 425

пример, 254

$_, переменная, 110, 388

.NET, 502

$^N, переменная, 363, 365, 413

$^R, переменная, 365, 393

$^W, переменная, 359

^, 148

метасимвол Java, 442

оптимизация, 302

^Subject: пример, 127, 196, 199, 297,

301, 350

Java, 128

.NET, 129

PHP, 130

Python, 130

$0, 363

Java, 453

PHP, 543

${0}, 543

$1, переменная, 178, 363, 366

Java, 453

.NET, 502

введение, 67

предварительное копирование, 425

${имя}

.NET, 502

{min, max}, 45


A

\A, 148, 169

оптимизация, 302

\a, 151

$all_matches, 538

и $matches, 537 размещение результатов

послойно, 539

с группировкой, 538

anchored(…), 433

AND, операция над символьными классами, 164

appendReplacement, метод, 454

appendTail, метод, 454

$ARGV, 111

ASCII, кодировка символов, 140, 151 AT&T Bell Labs, 118

awk

gensub, 231

границы слова, 174

доступ к тексту совпадений, 179 история, 118

поиск с заменой, 133


B

<B>…</B>, 211

\B, 174

\b, 95, 151, 174

Perl, 347

PHP, 521

граница слова и забой, 71, 74

метасимвол Java, 438

\b\B, 295

BLTN, Java, 290

BOL, 433

<br/>, тег, 570

BRE (базовые регулярные выражения), 119


C

\C, 157

PHP, 522, 523

\c, 155

/c, модификатор, 371, 380 C#

доступ к тексту совпадений, 179 строки, 137

Capture, объект, 516

.NET, 495

CaptureCollection, объект, 518

CDATA, 573

CharBuffer, класс, 445

charnames, директива, 351


CharSequence, интерфейс, 436, 446, 456,

473

CheckNaughtiness(), функция, 429

chr, функция, 497

Compilation failed, 561

compile, метод, 444

Compiled (.NET), модификатор режима, 292, 485, 487, 498, 506

CompileToAssembly, 515

Config, модуль, 351, 361

CR, 144, 442

create_function, функция, 549, 550

CR/LF, 442

CSV, парсинг, раскрутка регулярных выражений, пример, 330

currentTimeMillis(), функция, 290


D

\D, 77, 158

\d, 77, 158

Perl, 349

PHP, 521

Darth, 247 date_default_timezone_set(), функция,

289

DBIx::DWIW, модуль Perl, 315 debugcolor, 434

define-key, 135

Devel::FindAmpersand, модуль, 428

Devel::SawAmpersand, модуль, 428

Dr, ключ командной строки, 434


E

\e, 110, 151

\E, метасимвол

Java, 440, 470, 480

/e, модификатор, 384, 385 ECMAScript (.NET), модификатор

режима, 485, 489, 498, 506

ed, редактор, 117 egrep

границы слова, 174

доступ к тексту совпадений, 179 нечувствительность к регистру

символов, 39

обзор диалектов, 124

поддержка обратных ссылок, 194 поиск повторяющихся слов, пример,

47

пример использования, 39

реализация механизма регулярных выражений, 232

сводка метасимволов, 58

эволюция, 118 Emacs

re-search-forward, 134

границы слова, 174

доступ к тексту совпадений, 179 поиск, 134

регулярные выражения в строковом формате, 135

синтаксические классы, 168

управляющие символы, 155

end, метод, 450

English, модуль, 428

ERE (расширенные регулярные выражения), 119

ereg, семейство, 519

Escape-последовательности ANSI, 111

eval, функция, 385

Explicit, параметр, 492 ExplicitCapture (.NET), модификатор

режима, 485, 498, 506


F

\f, 151

введение, 71

FF, 144

find, метод, 448

flags, метод, 470

flex, описываемые версии, 123 floating 'строка', 433

foreach, if и while, сравнение, 385


G

\G, 171, 265, 529

.NET, 484

метасимвол, расширенный пример, 475

нетривиальный пример, 172

оптимизация, 302

якорный метасимвол, 379, 380

/g

введение, 79

модификатор, 371, 374, 375, 380, 384 с объектами регулярных

выражений, 424

gensub, функция, 231

GetGroupNames (метод объекта Regex), 505


GetGroupNumbers (метод объекта Regex), 505

gettimeofday(), функция, 289 GNU awk

gensub, 231

описываемые версии, 123 GNU egrep

описываемые версии, 123 поддержка обратных ссылок, 194 реализация механизма регулярных

выражений, 232 GNU Emacs

обзор диалектов, 124

описываемые версии, 123 GNU grep

описываемые версии, 123

поиск кратчайшего совпадения, 231 GNU sed, описываемые версии, 123 GPOS, 433

grep

Perl, 390

диалект регулярных выражений, 118 как акроним, 117

ключ -y, 118

обзор диалектов, 124

эволюция, 118

group, метод, 450

Group, объект (.NET), 495 Capture, 517

Captures, 509

Index, 509

Length, 509

Success, 509

ToString, 509

Value, 509

создание, 508

GroupCollection, объект, 518

groupCount, метод, 450 GroupNameFromNumber (метод объекта

Regex), 505

GroupNumberFromName (метод объекта Regex), 505

Groups, метод (объект Match), 507


H

hasAnchoringBounds, метод, 463

hasTransparentBounds, метод, 462 height, атрибут, Java-пример, 473 hitEnd, метод, 465

$HostnameRegex, переменная, 106, 179,

367, 420

HTML, пример, 532, 543, 545, 549, 574

<HR>, пример, 245

URL, 104, 258, 260, 367, 385

кодирование, 492

парные теги, 211

парсинг, 380

подготовка, 492

поиск тегов, пример, 251 преобразование текста, 97

проверка, 172

ссылки, пример, 253

теги, 24, 43, 427

htmlspecialchars, функция, 545

HTTP, пример, 552

HTTP URL, пример, 51, 253, 258, 260,

318, 367, 385

http://regex.info/, сайт, 429

$HttpUrl, переменная, 367, 413, 420

http://www.cpan.org/, сайт, 428

Hz, 144


I

/i, модификатор, 176

введение, 74

с функцией study, 430

i как y, 118

if, while и foreach, сравнение, 385 IgnoreCase (.NET), модификатор

режима, 130, 133, 485, 497, 506

IgnorePatternWhitespace (.NET), модификатор режима, 133, 485, 497,

506

IllegalArgumentException, исключение, 445

IllegalStateException, исключение, 449

<img>, тег, Java-пример, 473 implicit, 433

Imports, директива, 490, 493, 513

«In» и «Is», префиксы, 160 Index, метод

объекта Group, 509

объекта Match, 507 IndexOutOfBoundsException, исключе-

ние, 448, 449, 453

IP-адрес, пример, 236, 376, 379

Iraq, 35

Is и In, сравнение, Perl, 349 IsMatch (.NET), 491


IsMatch (метод объекта Regex), 499 ISO-8859-1, кодировка символов, 120,

140


J

Java, 436

BLTN, 290

\E, метасимвол, 480

find, метод, 448

JIT, 290

\Q, метасимвол, 480

, 146

split, метод, 470

виртуальная машина, 290

границы слова, 174

диалект регулярных выражений, 438 доступ к тексту совпадений, 179 завершители строк, 442

закрепление границ области поиска, 463

код примера, 261, 271, 289

область поиска, 457

объединение методов в конвейер, 463 объектная модель, 443

описываемая версия, 436

ошибки, 436, 440, 467, 476, 480

позиция дополнения, 447

позиция совпадения, 447, 457 поиск с заменой, 451

примеры программного кода, 443, 448, 451, 455, 463

прозрачность границ области поиска, 461

разбор данных CSV, пример, 476 разбор данных, разделенных

запятыми, пример, 271 различия между версиями, 477 режимы поиска, 440

для метасимвола точка, 442 свойства Юникода, 441

текущая позиция, 447, 478

хронометраж, 289

Юникод, 441

java.lang.Character, пакет, 442 java.util.regex

описываемые версии, 123

java.util.Scanner, пакет, 465

Jeffs, пример, 90

JfriedlsRegexLibrary, 513

JIT, компилятор, 487

Java, 290

JRE, среда выполнения Java, 290


L

\l, 351

\L…\E, 352

Latin-1, кодировка символов, 120, 140

lc(), функция, 352

lcfirst(), функция, 351 Length, метод

объекта Group, 509 объект а Match, 507

$LevelN, переменная, 396, 411 lex

$, 148

история, 118

точка, 147

LF, 144, 442

LIFO, возврат, 204 local, ключевое слово

во встроенном коде, 402 local, функция, 358

localtime, функция, 356, 385, 420

lookingAt, метод, 449

LS, 145, 442

M

/m, 176

Perl, 349 m/…/

введение, 64

makudonarudo, пример, 210, 282

Match, 130

Match (.NET) Success, 130 Match (.NET), объект, 495

Captures, 508, 517

Empty, 512

Groups, 507

Index, 507

Length, 507

NextMatch, 508

Result, 508

Success, 507

Synchronized, 508

ToString, 507

Value, 507

использование, 507

создание, 499, 508

Match (метод объекта Regex), 499 MatchCollection, объект, 500


matcher, метод, 445

Matcher, объект, 446

appendReplacement, метод, 454

appendTail, метод, 454

end, метод, 450

find, метод, 448

group, метод, 450

groupCount, метод, 450

hasAnchoringBounds, метод, 463

hasTransparentBounds, метод, 462

hitEnd, метод, 465

lookingAt, метод, 449

matches, метод, 449

pattern, метод, 468

quoteReplacement, метод, 452

region, метод, 460

regionEnd, метод, 460

regionStart, метод, 460

replaceAll, метод, 451

replaceFirst, метод, 452

requireEnd, метод, 465

reset, метод, 468

start, метод, 450

toMatchResult, метод, 450

toString, метод, 469

useAnchoringBounds, метод, 463

usePattern, метод, 468, 475

useTransparentBounds, метод, 462

аргумент замена, 453

область поиска, 457

$matches и $all_matches, 537 Matches (метод объекта Regex), 500

$matches, аргумент, 532

matches, метод, 449, 470

MatchEvaluator, 501

mb_ereg, семейство, 519

MBOL, 433

{min, max}, 45

minlen, длина, 433

MSIL (Microsoft Intermediate Language), 487

Multiline (.NET), модификатор режима, 485, 497, 506

MungeRegexLiteral, функция, 409, 415 my, переменные во встроенном коде, 405 MySQL, описываемые версии, 123


N

\n, 77, 151

введение, 71

зависимость от операционной системы, 152

\N{имя}, 351

NEL, 144

$NestedStuffRegex, переменная, 407,

414

.NET, 481

$+, 254

JIT-компиляция, 487

MSIL (Microsoft Intermediate Lan- guage), 487

URL, пример, 257

границы слова, 174

диалект регулярных выражений, 485 обзор диалектов, 124

объектная модель, 494

операция вычитания для символьных классов, 483

описываемая версия, 481

поиск с заменой, 492, 501

работа с регулярными выражениями, 129

ретроспективная проверка, 484

хронометраж, 291

.NET Framework описываемые версии, 123

New Regex, 130, 132, 493, 499

NextMatch (метод объекта Match), 508 no re 'debug', директива, 432

no-match-vars, директива, 428

None (.NET), 498, 506


O

/o, модификатор, 421

с объектами регулярных выражений, 424

oneself, пример, 399

Options (метод объекта Regex), 505 OR, операция над символьными

классами, 164

osmosis, 355

overload, директива, 410


P

\p{^…}, 164, 349

\P{…}, 159, 164

Java, 439, 441, 480

\p{…}, 159, 349

Java, 439, 441, 480

Perl, 164


\p{All}

Perl, 349

\p{all}, 441

\p{Any}, 164

Perl, 349

\p{Assigned}, 164

Perl, 349

\p{C}, 159

Java, 441

\p{Cc}, 161

\p{Cf}, 161

\p{Close_Punctuation}, 161

\P{Cn}, 165

\p{Cn}, 161, 441, 484

Java, 441

\p{Co}, 161

\p{Connector_Punctuatlon}, 161

\p{Control}, 161

\p{Currency_Symbol}, 161

\p{Cyrillic}, 162, 164

\p{Dash_Punctuation}, 161

\p{Decimal_Digit_Number}, 161

\p{Enclosing_Mark}, 160

\p{Final_Punctuation}, 161

\p{Format}, 161

\p{Greek}, 164

\p{Han}, 162

\p{Hebrew}, 162

\p{Hiragana}, 162

\p{InCyrillic}, 164

\p{Inherited}, 162

\p{Initial_Punctuation}, 161

\p{InTibetan}, 162

\p{IsCommon}, 162

\p{IsCyrillic}, 164

\p{IsGreek}, 164

\p{IsL}, 164

\p{IsTibetan}, 162

\p{javaJavaIdentifierStart}, 442

\p{Katakana}, 162

\p{L&}, 160, 164

Perl, 349

\p{L}, 159, 174, 438

\p{Latin}, 162

\p{Letter}, 159, 164

Perl, 349

\p{Letter_Number}, 161

\p{Line_Separator}, 160

\p{Ll}, 160, 484

\p{Lm}, 160, 484

\p{Lo}, 160, 484

\p{Lowercase_Letter}, 160

\p{Lt}, 160, 484

\p{Lu}, 160, 484

\p{M}, 157, 159

\p{Mark}, 159

\p{Math_Symbol}, 161

\p{Mc}, 160

\p{Me}, 160

\p{Mn}, 160

\p{Modifier_Letter}, 160

\p{Modlfier_Symbol}, 161

\p{N}, 159

\p{Nd}, 161, 438, 484

\p{Nl}, 161

\p{No}, 161

\p{Non_Spacing_Mark}, 160

\p{Number}, 159

\p{Open_Punctuatlon}, 161

\p{Other}, 159

\p{Other_Letter}, 160

\p{Other_Number}, 161

\p{Other_Punctuation}, 161

\p{Other_Symbol}, 161

\p{P}, 159

\p{Paragraph_Separator}, 161

\p{Pc}, 161

\p{Pd}, 161

\p{Pe}, 161

\p{Pf}, 161

Java, 441

\p{Pi}, 161

Java, 441

\p{Po}, 161

\p{Private_Use}, 161

\p{Ps}, 161

\p{Punctuation}, 159

\p{S}, 159

\p{Sc}, 161

\p{Separator}, 159

\p{Sk}, 161

\p{Sm}, 161

\p{So}, 161

\p{Space_Separator}, 160

\p{Spacing_Combining_Mark}, 160

\p{Symbol}, 159

\p{Titlecase_Letter}, 160

\p{Unassigned}, 161, 164

Perl, 349

\p{Uppercase_Letter}, 160

\p{Z}, 159, 438, 484

\p{Zl}, 160


\p{Zp}, 161

\p{Zs}, 160

\p{Рс}, 484

panic: top_env, 399

Pascal, 62, 232

поиск комментариев, 323 Pattern

CANON_EQ, 143 CASE_INSENSITIVE, ключ

компиляции, 128, 132, 145, 444

и ошибка, 468

COMMENTS, ключ компиляции, 132, 440

compile, метод, 444

DOTALL, ключ компиляции, 440, 442

flags, метод, 470

matcher, метод, 445

matches, метод, 470

MULTILINE, ключ компиляции, 440, 442

pattern, метод, 470

quote, метод, 470

split, метод, 470

toString, метод, 470 UNICODE_CASE, ключ компиляции,

444

UNIX_LINES, ключ компиляции, 440, 442

pattern, метод, 468, 470 Pattern.CANON_EQ, ключ компиляции,

440

Pattern.CASE_INSENSITIVE, ключ компиляции, 440

Pattern.LITERAL, ключ компиляции, 440

PatternSyntaxException, исключение, 443, 445

Pattern.UNICODE_CASE, ключ компиляции, 440

PCRE

\w, 158

механизм «study», 529 модификатор шаблона X, 529 обзор диалекта регулярных

выражений, 521

описываемые версии, 123

рекурсивные ссылки, 564

рекурсивный поиск, 563

сайт, 123

PCRE, библиотека, 520

описываемая версия, 521

Perl, язык программирования, 61

$/, 61

$^W, переменная предупреждения, 359

глобальные и закрытые переменные, 357

границы слова, 174

доступ к тексту совпадений, 179 контекст, 356

краткий курс, 63

кэширование, 419

модификаторы, 354

обзор диалектов, 124

ограничение количества фрагментов при разбиении, 388

операторы регулярных выражений, 346

описываемые версии, 123, 343 параметры командной строки

-0, 62

-c, 432

-Dr, 434

-e, 62, 81, 432

-i, 81

-M, 432

-Mre=debug, 434

-n, 62

-p, 81

-w, 64, 391, 432

поиск с заменой, 383 предупреждения, 64

$^W, переменная, 359

use warnings, 391

проблемы эффективности, 416 разбор данных, разделенных

запятыми, пример, 266

ретроспективная проверка, 175 сильные и слабые стороны, 346 эволюция, 120

Perl Porters, 122

PHP, 519

\w, 158

аргумент шаблон, 525

границы слова, 174

доступ к тексту совпадений, 179 именованные сохранения, 532, 564

механизм «study», 529

«недостающие» функции, 558 обзор диалекта регулярных

выражений, 521

описываемые версии, 123, 521


поиск с заменой, 542

разбор данных в формате CVS, пример, 569

разделители регулярных выражений, 526, 530

рекурсивные ссылки, 564

рекурсивный поиск, 563

ретроспективная проверка, 523 строки в апострофах, 525

функция обратного вызова, 548, 550

хронометраж, 288

эффективность, 566

\pL, PHP, 521

\pN, PHP, 521

pos(), функция, 171, 378 POSIX

[=…=], 168

[:…:], 166

[…..], 167

BRE (базовые регулярные выражения), 119

ERE (расширенные регулярные выражения), 119

групповые выражения, 166

локальный контекст, 167

обзор, 119

объединяющие последовательности, 167

правило самого длинного совпадения, ближнего к левому краю, 226

символьные классы, 166

и локальный контекст, 167 символьные эквиваленты, 168

POSIX НКА

пример с возвратами, 283 проверка типа механизма, 190

preg, семейство, 519

preg_grep, функция, 556

PREG_GREP_INVERT, флаг, 556

preg_match, функция, 531

смещение, 536

preg_match_all, функция, 536

PREG_OFFSET_CAPTURE, флаг, 535,

538, 540

preg_pattern_error, функция, 562

PREG_PATTERN_ORDER, флаг, 538

preg_quote, функция, 178, 557

preg_regex_error, функция, 563

preg_regex_to_pattern, функция, 558

preg_replace, функция, 542

preg_replace_callback, функция, 548

preg_split, функция, 551 PREG_SPLIT_DELIM_CAPTURE, флаг,

553, 554

PREG_SPLIT_NO_EMPTY, флаг, 554 PREG_SPLIT_OFFSET_CAPTURE,

флаг, 554

Procmail, описываемые версии, 123, 127

PS, 145, 442

Python

\Z, 148

границы слова, 174

доступ к тексту совпадений, 179 модификаторы режима, 176

описываемые версии, 123

работа с регулярными выражениями, 130

ретроспективная проверка, 175

строки, 138

хронометраж, 293

\pZ, PHP, 521


Q

\Q, метасимвол Java, 440, 470, 480

\Q…\E, 352

Qantas, 35

qed, редактор, 117

qr/…/, 107

quote, метод, 178, 470

quoteReplacement, метод, 452


R

\r, 77, 151

зависимость от операционной системы, 152

r"…", 138

re 'debug', директива, 432 Regex (.NET), объект

CompileToAssembly, 513, 515

Escape, 511

GetGroupNames, 505

GetGroupNumbers, 505

GroupNameFromNumber, 505

GroupNumberFromName, 505

IsMatch, 491, 509

Match, 491, 495, 509

Matches, 500, 509

Options, 505

Replace, 492, 501, 509

RightToLeft, 505

Split, 504, 509


ToString, 505

Unescape, 512

исключения, 496

использование, 499

создание, 495, 497

параметры, 497

Regex.Escape, 178 RegexOptions

Compiled (.NET), модификатор режима, 292, 485, 487, 498, 506

ECMAScript, модификатор режима, 485, 489, 498, 506

ExplicitCapture, модификатор режи- ма, 485, 498, 506

IgnoreCase, модификатор режима, 130, 133, 485, 497

IgnorePatternWhitespace, модифика- тор режима, 133, 485, 497, 506

Multiline, модификатор режима, 485, 497, 506

None, 498, 506

RightToLeft, модификатор режима, 485, 489, 498, 506

Singleline, модификатор режима, 485, 498

RegexOptions.RightToLeft, 504

region, метод, 460

regionEnd, метод, 460

regionStart, метод, 460

reg_match, функция, 538

regsub, 134

Replace (метод объекта Regex), 501 replaceAll, метод, 451

replaceFirst, метод, 452

requireEnd, метод, 465

re-search-forward, 134

reset, метод, 468

Result (метод объекта Match), 508 RightToLeft (.NET), модификатор режима, 485, 489, 498, 504, 506

RightToLeft (метод объекта Regex), 505 Ruby

границы слова, 174

доступ к тексту совпадений, 179 модификаторы режима, 176

описываемые версии, 123

хронометраж, 292

rx, 232

S

\S, 77, 84, 158

Emacs, 169

/s, 176

\s, 77, 158

Emacs, 168

Perl, 349

PHP, 521

введение, 74

s/…/…/, оператор, 78, 383

SBOL, 433

sed

границы слова, 174

доступ к тексту совпадений, 179 точка, 147

Singleline (.NET), модификатор режима, 485, 498, 506

split и сохраняющие круглые скобки

.NET, 504

Split (метод объекта Regex, 504 split, метод

Java, 470

ограничение числа совпадений, 472

split, оператор, 387

start, метод, 450

Strict (параметр), 492

strict, директива, 357, 403, 415

String, класс, 445

StringBuffer, класс, 445, 456, 473

StringBuilder, класс, 456, 473 str_ireplace, функция (PHP), 542 str_replace, функция (PHP), 542 study, функция, 429

когда не следует использовать, 430 Success, метод

объекта Group, 509

объекта Match, 507 System.currentTimeMillis(), функция,

290

System.Text.RegularExpressions, 490,

493


T

\t, 77, 151

введение, 71

T1me::HiRes, модуль, 286


Tcl

[:<:], 124

[:>:], 124

regsub, 134

гибридные механизмы регулярных выражений, 298

границы слова, 174

доступ к тексту совпадений, 179 модификаторы режима, 176

обзор диалектов, 124

описываемые версии, 123 поиск с заменой, 134

реализация механизма регулярных выражений, 232

строки, 139

точка, 147

хронометраж, 293

this|that, пример, 298, 312, 319

time(), функция, 286

Time::HiRes, модуль, 429, 431

Timer(), функция, 292

toMatchResult, метод, 450 ToString, метод

объекта Group, 509

объекта Match, 507

объекта Regex, 505

toString, метод, 469, 470


U

\U, 155

\u, 155, 482

U+C0B5, 142

\U…\E, 352

uc(), функция, 352

ucfirst(), функция, 351

UCS-2, кодировка символов, 142 UCS-4, кодировка символов, 142 UnicodeData.txt, файл, 351

unicore, каталог, 351

URL, пример, 104, 318, 532

поиск, 258, 260

use charnames, директива, 351 use Config, 351

use strict, 357, 403

useAnchoringBounds, метод, 463

usePattern, метод, 468, 475

useTransparentBounds, метод, 462 UTF-16, кодировка символов, 142 UTF-8, кодировка символов, 142, 528

V

\v, 151

метасимвол, 435

\V, метасимвол, 435 Value

метод объекта Group, 509 VB.NET

доступ к тексту совпадений, 179 работа с регулярными выражениями,

129

строки, 137

vi, доступ к тексту совпадений, 179 Visual Studio .NET, 513

VT, 144


W

\W, 77, 158

\w, 77, 95, 158

Perl, 349

PHP, 158, 521

метасимвол Java, 438

различные варианты интерпретации, 125

w, ключ, 359

warnings, директива, 391

while, foreach и if, сравнение, 385 width, атрибут, Java-пример, 473 with eval, 433


X

\X, 143, 158

/x, 103, 176

Perl, 349

история, 122

\x, 144, 155, 482

Perl, 347

XML, 573

CDATA, 573

пример, 570, 573


Y

y, ключ в старой версии grep, 118 Yahoo!, 258


Z

\Z, 148, 169

Java

метасимвол, 442


PHP, 523

\z, 169, 529

метасимвол, 381


А

автоматический захват, оптимизация, 307

алфавиты, 162, 349

PHP, 523

альтернативы, порядок следования, 571 аналогии

возврат

стопка тарелок, 204

хлебные крошки, 202 в порядке очереди, 197

зарядка аккумуляторов, 228

с автомобилем, 57, 114

с бензиновым двигателем, 187 с двигателем, 186

с мячом, раскрутка цикла, 319

с пленкой (функция local в языке Perl), 360

с трансмиссией, 192

с электродвигателем, 186 апострофы

как ограничители регулярного выражения, 353, 384

аргумент замена Java, 453

аргумент шаблон, 525

атомарная группировка, 317

введение, 180

для повышения эффективности, 218, 327

подробности, 216

пример, 249, 253, 266, 397, 408

сущность, 217

Ахо Альфред (Alfred Aho), 118, 228


Б

базовый символ, 142

балансировка регулярных выражений, 235

безусловное кэширование, 419 бесконечный перебор, как избежать, 322 бесконечный поиск совпадений, 279,

397, 408

обнаружение, 280

описание, 280

блоки, 349, 441, 480, 484

Бойер-Мур (Воуеr-Moore), 300

более раннее совпадение выигрывает, 191


В

версии программ, упоминаемых в книге, 123

вертикальная табуляция, 144

\s, Perl, 349

взаимодействие регулярных выражений с логикой программы, 70

видимость, лексическая и динамическая, 361

виртуальная машина, 290

«разогрев», 291

вложенные конструкции, 570

.NET, 515

Perl, 393, 407

PHP, 563, 570

возврат, 209

LIFO, 204

введение, 202

минимальный поиск, пример, 206 несовпадение, 205

при позиционной проверке, 220 сохраненные состояния, 204

сущность, 215

эффективность, 227

возврат каретки, 144, 442 возвраты

POSIX НКА, пример, 283 бесконечный поиск совпадений, 280 и конструкции выбора, 285 количество проверок, 280 обнаружение лишних возвратов, 306 с глобальной точки зрения, 282 строки с продолжением, 275, 277

экспоненциальный поиск, 280 возвращение к реальности, 279 восьмеричные коды, 153 восьмеричные числа

и обратные ссылки, 489

«вредные» переменные, 426

время суток, 52

встроенный код, 397

local, ключевое слово, 402 и переменные my, 405

регулярные выражения, 393

выбор, 181

введение, 37


и круглые скобки, 37 вывод всех совпадений, 399

выделение литерального текста, 312 выделение якорей, оптимизация, 312 вычитание символьных классов, 165


Г

гибридный механизм регулярных выражений, 231

глобальные и закрытые переменные, Perl, 357

Гослинг Джеймс (James Gosling), 121 границы слов

\<…\>

egrep, 39

Perl, 349

введение, 39

границы строк, 147

группировка и обратные ссылки, 45 групповые выражения, 166


Д

двигатель, аналогия с, 186 делегат, 501

денежные суммы в долларах, пример, 50 диалекты

обзор, 124

определение, 53 регулярных выражений

Java, 438

.NET, 485

PCRE, 521

Perl, 347

PHP, 521

диалитика, 143

динамическая видимость, Perl, 355, 357 и лексическая видимость, 361

динамические регулярные выражения, 393

директивы charnames, 351

Imports, 490, 513 no re 'debug', 432 no-match-vars, 428

overload, 410

re 'debug', 432

strict, 357, 403, 415

warnings, 391 ДКА

введение, 188, 200

обратные ссылки, 194, 231

отложенные вычисления, 230 проверка типа механизма, 190 простота реализации, 231

расшифровка аббревиатуры, 201

«самое длинное совпадение, ближнее к левому краю», 225

сравнение с НКА, 200, 229, 279, 281

эффективность, 229

Доска Позора No Dashes Or Spaces, 543


Е

\Е, 352


З

завершающий контекст, 230

завершители строк, 144

Java, 442

зависимость от операционной системы, 152

Заводни Джереми (Jeremy Zawodny), 315

закрепление границ, 463

Java, 463

замена, аргумент, 545

PHP, 542

s/…/…/, 78

порядок следования элементов, 546, 549

замыкания, 407

захватывающие квантификаторы, 184,

219, 317, 565, 572

имитация, 411

использование для повышения эффективности, 317, 327, 328, 571

оптимизация, 307

пример, 249, 253

Змиевски Андрей (Andrei Zmievski), 520


И

имена переменных, пример, 49 имена файлов, пример, 239 именованные символы Юникода, 351 именованные сохранения, 180

.NET, 484

PHP, 532, 540, 564

имитация, 413 имитация

атомарной группировки, 221


захватывающих квантификаторов, 411

именованного сохранения, 413

интерполяция переменных, 386 исключение по первому символу,

оптимизация, 316

метасимволов начала и конца слов в Perl, 409

операций над символьными классами, 166

переменной $&, 427

переменной $', 427

переменной $`, 427

имя пользователя, пример, 131 в URL, пример, 104

имя файла, пример, 526 имя хоста

VB.NET, пример, 257 в URL, пример, 104 поиск, 258, 260

пример, 51, 131, 180, 318, 325, 532

проверка, пример, 255 инвертированные классы

и минимальные квантификаторы, 213

инвертированный поиск, 373 инвертированный символьный класс

введение, 34

инструкции обработки, 573

интегрированный интерфейс, 127 кэширование при компиляции, 298

интервал, введение, 45

интервальное преобразование регистра, 352

интервальные модификаторы режимов, 527

интерполяция, 350

PHP, 137

введение, 107

встроенного кода в Perl, 404 имитация, 386

кэширование, 420

результатов тестов, 305 исключение лишних круглых скобок,

оптимизация, 304

исключение лишних символьных классов, оптимизация, 304

исключение по первому символу, 302 оптимизация, 316

исключение случайных совпадений, 337

исключения IllegalArgumentException, 445

IllegalStateException, 449

IndexOutOfBoundsException, 448,

449, 453

PatternSyntaxException, 443, 445 история развития

\+, 119

awk, 118

egrep, 118

grep, 118

lex, 118

Perl, 120

PHP, 520

sed, 118

/х, 122

происхождения регулярных выражений, 116

символ подчеркивания в \w, 120


К

«кавычки» многосимвольные, 211

квантификаторы, 43

*, введение, 43

?, введение, 42

и возврат, 206

(), 46

+, введение, 43

захватывающие, 219, 565, 572

для повышения эффективности, 317, 327, 328, 571

и возврат, 207

упрощение, оптимизация, 303 классы

исключение по первому классу, 302 клиентская виртуальная машина, 290 книга зеленого и красного дракона, 228 код примера Java, 261, 271, 289 кодировка символов

ASCII, 140

Latin-1, 120, 140

UCS-2, 142

UCS-4, 142

UTF-16, 142

UTF-8, 142, 521, 528

проблемы, 140 кодовый пункт

введение, 141

выходящий за пределы U+FFFF, 144 комбинационный символ, 142, 158


комментарии, 150, 177

Java, 132

.NET, 497

XML, 573

поиск комментариев Pascal, 323 поиск комментариев С, 331

компиляция кэширование, 297

однократная, модификатор /o, 421 регулярных выражений, 487

Констейбл Роберт (Robert Constable), 116

конструкции выбора и возвраты, 285

и эффективность, 275, 285

максимализм, 222

порядок следования альтернатив, 239, 276, 318

изменение порядка следования для достижения эффективности, 279

упорядоченный выбор, 223

контекст, 374

использования регулярных выражений, 238

метасимволов, 71

регулярного выражения Perl, 356 косвенная привязка к началу строки,

оптимизация, 302

круглые скобки, 193 split, функция

.NET, 504

в операторе split Perl, 392

вложенные, 515, 563

и конструкция выбора, 37

и обратные ссылки в egrep, 45 именованное сохранение, 180, 413,

532, 540

как\(…\), 117

не участвовавшие в совпадении, 533, 556

несохраняющие, 72

оптимизация исключением, 304

парные, 515

сложности, 243

рекурсивные ссылки, 564

сбалансированные, 563

сохранение, Perl, 68

сохраняющие, 364

и механизм ДКА, 194

кэширование, 297

.NET, 510

PHP, 566

Perl, 419

Tcl, 299

безусловное, 419

интерполяция, 420

при компиляции, 297

для интегрированного интерфейса, 298

для объектно-ориентированного интерфейса, 300

для процедурного интерфейса, 299 сокращение затрат на компиляцию,

419


Л

лексическая видимость, 361 литералы

механика поиска совпадений, 193

в регулярных выражениях, 139, 350,

354, 371

обработка, 419

литеральный интервал, 177

литеральный режим, 149 литеральный текст

выделение, 312

предварительная проверка обязатель- ных символов/подстрок, 432

локализация, 358

локальный контекст, 167

обзор, 119

Лорд Том (Tom Lord), 232


М

максимализм введение, 195

и возврат, 207

и минимализм, 313

изменение, 530

конструкция выбора, 222

локализация, 277

максимальные конструкции всегда выбирают совпадение, 213

принцип, 204

проблемы, 210

сущность, 215

чрезмерная жадность, 196

максимальные квантификаторы, 183


метасимвол

в различных контекстах, 34 определение, 53

метасимволы начала и конца слов имитация, 409

механизм, управляемый регулярным выражением, 198

и обратные ссылки, 366

механизм, управляемый текстом, 200 механизмы регулярных выражений

гибридные, 231, 294, 298 определение типа механизма, 190

с использованием бесконечного поиска, 281

сравнение, 200, 229 механика поиска, POSIX

Perl, 402

механика применения регулярных выражений, 296

минимализм, 212

и максимализм, 313 минимальные конструкции всегда

выбирают совпадение, 213

оптимизация, 304

сущность, 215

минимальные квантификаторы, 184

многоликие метасимволы, 71

многосимвольные «кавычки», 211

«многострочный» режим, 147 модификаторы

/g, 79

/i, 74

/osmosis, 355

базовые, Perl, 354

в объектах регулярных выражений, 368

неизвестный, 530

пример с пятью модификаторами, 381 фиксация режимов поиска, 368

модификаторы режимов, 145, 176, 485 модификаторы шаблонов

A, 528, 529

D, 523, 528, 529

e, 528, 544, 550

I, 527

m, 523, 527

PHP, 527

S, 317, 528, 544, 567

s, 527

U, 528, 530

u, 521, 527, 535

X, 527, 529

x, 523, 527

ошибка – неизвестный модификатор, 530


Н

население, пример, 88

«недостающие» функции, PHP, 558 нейрофизиологи, 116

неопределенный контекст, 356

нервная система, 116

нерегулярные выражения, 228 несколько значений метасимволов, 71 несовпадение, 205

атомарная группировка, 218 несохраняющие круглые скобки, 72,

179

неудача, принудительная, 399 нечувствительность к регистру

символов egrep, 39

введение, 39 НКА

введение, 198

и конструкция выбора, 222 и максимализм, 207

первое упоминание, 188

преимущества, 199

проверка типа механизма, 190 простота реализации, 231

расшифровка аббревиатуры, 201

сравнение с ДКА, 200, 229 теория и практика, 228 эффективность, 229

нониллион, 280

нормальные, символы, 321

нуль-байт, 153

нуль-символы и точка, 157


О

область поиска hitEnd, метод, 465

Java, 457

requireEnd, метод, 465

дополнительные примеры, 473

закрепление границ, 463

методы, которые переинициализиру- ют область, 459

прозрачность границ, 461


обнаружение лишних возвратов, оптимизация, 306

обработка биржевых котировок, пример, 79

обработка почты, пример, 81 обратные ссылки, 178

в egrep, 45

ДКА, 194, 231

и восьмеричные числа, 489 на совпавший текст, 46

общая неудача, 297

общий шаблон раскрутки цикла, 321, 322

объединение методов в конвейер, 463 Java, 463

объединяющие последовательности, 167 объектная модель

Java, 443

.NET, 494

объектно-ориентированный интерфейс, 127

кэширование при компиляции, 300 объекты регулярных выражений, 367

/g, модификатор, 424

/o, модификатор, 424

и повышение эффективности, 370, 422

просмотр, 369

ограничение, preg_split, 551 ограничение количества фрагментов при

разбиении Perl, 388

PHP, 551

ограничение числа совпадений, Java, 472

ограничения на количество возвратов, 293

округление денежных величин, пример, 213, 223

с использованием атомарной группировки, 217

с использованием захватывающих квантификаторов, 216

операторы регулярных выражений,

Perl, 346

операции с классами, 164 опережающая проверка, 175

<B>…</B>, 213

Java, 440

введение, 88

имитация атомарной группировки, 221

имитация операций с множествами, 166

оптимизация имитацией, 316 позитивная и негативная, 96 пример, 90

описываемые версии Java, 436

.NET, 481

PCRE, 521

Perl, 343

PHP, 521

оптимизация, 294

BLTN, 290

JIT, 290

компиляция, 487

автоматический захват, 307

выделение якорей, 312

исключение лишних круглых скобок, 304

исключение лишних символьных классов, 304

исключение по первому символу, 302, 316

использование якорных метасимволов, 241

конкатенация подстрок, 303 косвенная привязка к началу строки,

302

минимальные квантификаторы, 304 обнаружение лишних возвратов, 306 отложенные вычисления, 230

подавление состояний, 307 предварительная проверка

обязательных символов, 300 предотвращение экспоненциального

поиска, 306

при смещении текущей позиции, 301 привязка к концу текста, 302 привязка к началу текста, 301 проверка внутренних литералов, 303 разделение регулярных выражений,

314

стандартные способы, 294

упрощение квантификаторов, 303

учет длины текста, 301, 303

учет необходимых элементов, 308 эквивалентность малых

квантификаторов, 308

якорные метасимволы, 193


отказ, атомарная группировка, 218 отладка

$&, переменная, 398

$', переменная, 398

$`, переменная, 398

на стадии выполнения, 433 объектов регулярных выражений,

369

регулярных выражений, 431

с помощью встроенного кода, 398 отложенные вычисления, 230

отсутствие совпадения, 538 ошибки

в Java, 436, 440, 467, 476, 480

в реализации метода hitEnd, 467


П

параметры

-c, 432

-Dr, 434

-e, 432

-M, 432

-Mre=debug, 434

-w, 359, 432

перевод на язык регулярных выражений, 335

перевод строки, 144, 442

перевод формата, 144

перегрузка в регулярных выражениях, 352, 409

пример, 410

перекомпиляция, при необходимости, 420

переменные

«вредные», 426

значения которых задаются после совпадения

Perl, 363

интерполяция, 412

полностью уточненное имя, 357 предварительное копирование, 425

Пиньян Джефф (Jeff Pinyan), 302 письмо на стандартном бланке,

примеры, 78 побайтовое совпадение

PHP, 523

подавление состояний, оптимизация, 307

поддержание синхронизации, 264

подстановка s/…/…/, 383

имени входного файла, 111 подстроки

исключение по первому символу, 302 конкатенация, оптимизация, 303

позиционная проверка, 88

Perl, 349

и возврат, 220

не «поглощает» текст, 88 условная конструкция, 183

позиция дополнения, 447

позиция совпадения, 447

в Java, 457

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

атомарной группировки, 329 захватывающих квантификаторов,

328

поиск

IP-адреса, пример, 236 URL на практике, 258

адресов электронной почты, пример, 131

Java, 132

.NET, 132

вложенных конструкций, 407

идентификаторов, 49

имен пользователя и хоста, пример, 101

повторяющихся слов, пример, 47 Emacs, 135

Perl, 61, 108

поиск с заменой awk, 133

Emacs, 134

Java, 451, 456

.NET, 492, 501

Perl, 383

PHP, 542

Tcl, 134

поиск самого длинного совпадения, 400 поиск самого длинного совпадения,

ближнего к левому краю, 402 поиск совпадений, 370

бесконечный, 279, 397, 408

обнаружение, 280

описание, 280

возврат, небольшой пример, 203 вывод информации в процессе

поиска, 398


ДКА и НКА, 281

инвертированный, 373 исключение нежелательных

совпадений, 245

контекст, 356

неопределенный, 356

скалярный, 356, 374

списковый, 356, 374 механика

.*, 196

литералы, 193

максимализм, введение, 195 НКА и ДКА, 201

последствия, 201

символьные классы, 193 сохраняющие круглые скобки, 193 точка, 193

якорные метасимволы, 193 минимальный поиск, пример, 206 отсутствие совпадения, 538

побочные эффекты, 382 поиск без возврата, 205 поиск после возврата, 205 пустое совпадение, 538

режимы, 145

самого длинного, 400

самого длинного, ближнего к левому краю, 225, 402

скалярный контекст, 377

скорость, 229

ссылки HTML, 253

теги HTML, 251

текст в ограничителях, 246 обобщенное решение, 247

эффективность, 227 поиск справа налево, 488

полностью уточненное имя, 357 порядок следования элементов в аргументах-массивах, 546

последовательности символов, заключенные в кавычки, пример egrep, 50

почтовые индексы, пример, 262 правила

более раннее совпадение выигрывает, 191

квантификаторы работают максимально, 195

правильность и эффективность, 277 предварительная проверка обязатель-

ных символов, оптимизация, 300

предварительное копирование, 425 предотвращение лишних операций, 294 предотвращение экспоненциального

поиска, оптимизация, 306

представления символов, 151 предупреждения

.*, 85

Perl, 64

use warnings, Perl, 391 отключение на время, 359

преобразование адресов электронной почты в ссылки, пример, 100

преобразование температуры, пример

.NET, 503

Perl, 63, 343

PHP, 525

преобразование типа, 356 префиксы изменения регистра

символов, 351

привязка к концу текста, оптимизация, 302

привязка к началу текста, оптимизация, 301

примеры

$+ (.NET), 254

^Subject, 301, 350

gr[ea]y, 32

<img>, тег, 473

Jeffs, 90

HTML, 524, 543, 545, 549, 574

<HR>, 245

URL, 258, 260, 367, 532

кодирование, 492

кодирование URL, 385

парные теги, 211

парсинг, 380

подготовка, 492

поиск тегов, 251

проверка, 172

разбор, 475

ссылки, 253

теги, 51, 427

HTML URL, 255

HTTP URL, 255

HTTP-ответ, 552

IP-адрес, 376, 379

.NET

$+, 254

URL, 257

oneself, 399

this|that, 298, 303, 312, 319


примеры

URL, 51, 104, 253, 367, 385, 532 VB.NET

имя хоста, 257

XML, 570, 573

атомарная группировка, 249, 253,

266, 397, 408

денежные суммы в долларах, 50 захватывающие квантификаторы,

249, 253

имена переменных, 49

имена файлов, 239, 526

имя пользователя, 131

в URL, 104

имя хоста, 131, 180, 318, 325, 532

Java, 261

в URL, 104

население, 88

обработка биржевых котировок, 79 обработка почты, 81

округление денежных величин, 213, 216, 223

с использованием конструкции выбора, 223

опережающая проверка, 90 перегрузка регулярных выражений,

410

письмо на стандартном бланке, 78 поиск IP-адреса, 236

поиск URL, 260

на практике, 258

поиск адресов электронной почты, 131

Java, 132

.NET, 132

поиск имен пользователя и хоста, 101 поиск повторяющихся слов

Emacs, 135

Perl, 61, 108

почтовые индексы, 262 преобразование адресов электронной

почты в ссылки, 100 преобразование текста в HTML, 97 преобразование температур

Java, 455

.NET, 503

Perl, 63, 343

PHP, 525

проверка имени хоста, 255

проверка файлов, 62

простой поиск с заменой, 452 пути к файлам, 239

пять модификаторов, 381 разбор данных CSV

Java, 476

разбор данных в формате CVS PHP, 569

разбор данных, разделенных запятыми, 266

Java, 271

разделение разрядов числа запятыми без ретроспективной проверки, 96 введение, 88

раскрутка многосимвольных ограничителей, 329

раскрутка регулярных выражений, парсинг CSV, 330

раскрутка цикла, 329, 565 строки в кавычках

makudonarudo, 210, 282 окончательное регулярное

выражение, 322 поддержка экранированных

кавычек, 247

раскрутка цикла, 327

убедительный пример, 275

строки продолжения, 330 числа с плавающей точкой, 245

примеры программного кода Java, 443, 448, 451, 455, 463

проблемы кодировки символов, 140 проверка

внутренних литералов, оптимизация, 303

имени хоста, пример, 255

на наличие «вредных» переменных, 428

пользовательского ввода перед интерполяцией, 404

типа механизма, 190 прозрачность границ, Java, 461 пропуски, удаление, 250

процедурный интерфейс, 127 кэширование при компиляции, 299

псевдосвойства, 349

пустое совпадение, 538 пути к файлам, пример, 239

пять модификаторов, пример, 381


Р

разбиение Perl, 386

PHP, 551

завершающие пустые элементы, 389 нетривиальное, 389

ограничение количества фрагментов Perl, 388

простейшее, 387

с сохраняющими круглыми скобками, Perl, 392

разбор данных в формате CVS, пример PHP, 569

разбор регулярных выражений, 486 разделение разрядов без ретроспектив-

ной проверки, пример, 96 разделение разрядов числа запятыми,

пример, 88

разделение регулярных выражений, оптимизация, 314

разделители в операторе замены, 384 разделители регулярных выражений

PHP, 526, 530

разделитель абзацев, 145, 442

разделитель строк, 145, 442 различия между версиями, Java, 477

«разогретая» виртуальная машина, 291 раскрутка выражения для поиска

комментариев С, 335 раскрутка многосимвольных

ограничителей, пример, 329

раскрутка цикла, 319, 565

общий шаблон, 322

пример, 565

расширенный режим привязки, 99 реализация механизма регулярных

выражений, 231 регулярные выражения

.NET

объект, создание, 130 аналогия с двигателем, 186 библиотека, 106

вызов подпрограммы, 564 динамическая видимость, Perl, 355 динамические, 393

история происхождения, 116

компиляция, 419

контекст, 356

кэширование, 297, 419, 510, 566

механика применения, 296

модификаторы, 354

необходимость балансировки, 235

ограничители, 352

операнды, 350

отладка, 431

перегрузка, 352, 394

недостатки, 412

по умолчанию, 371, 424

порядок обработки литералов, 354 предварительная компиляция, 229

проверка синтаксиса, 561

происхождение термина, 116

режимы поиска, 368

рекурсивные, 563

самое длинное совпадение, ближнее к левому краю, 225

списковый контекст, 356

регулярные множества, 116 режим поиска без учета регистра

символов, 145

/i, 74

Ruby, 145

с функцией study, 430 результаты поиска в Java, 447 рекурсивные ссылки

PCRE, 564

PHP, 564

рекурсивный поиск Java, 477

PCRE, 563

PHP, 563

ретроспективная проверка, 175

Java, 440

.NET, 484

Perl, 349

PHP, 523

позитивная и негативная, 96 совпадение с текстом произвольной

длины, 484 РНР

ретроспективная проверка, 175

строки, 137


С

С-комментарии поиск, 331

раскрутка, 335

Самая Загадочная Программа на Perl, 386


самое длинное совпадение, ближнее к левому краю, 225

самозакрывающиеся теги, 570

сбалансированные конструкции, 515,

563, 570

PHP, 570

сборка мусора, влияние на результаты хронометража, 291

свободное форматирование и коммента- рии, режим, 146

свойства Юникода, 159 Сези Рави (Ravi Sethi), 228

серверная виртуальная машина, 290 символы

зависимость от операционной системы, 152

и комбинации, 142

исключение по первому символу, 302, 308

оптимизация, 316

комбинационные, 142, 158 новой строки и HTTP, 153 определение, 55

подчеркивания в \w, история, 120 представление, 151

сокращенные обозначения, 151

управляющие, 155

символьные классы, 155

введение, 32

в сравнении с точкой, 156 вычитание, 165

групповые выражения в стандарте POSIX, 166

и конструкция выбора, 37

и минимальные квантификаторы, 213

инвертированные

символ новой строки, 157 интервалы, 156

исключение, оптимизация, 304 как своеобразный мини-язык, 34 механика поиска совпадений, 193 операции с классами, 164 операция вычитания, 483

операция объединения, 165

операция пересечения, 165

позитивное условие, 156 простое вычитание классов, 163

символьные эквиваленты, 168 синтаксические классы Emacs, 168 синхронизация совпадений, 263

скалярный контекст, 356, 374, 377

сканеры, 464, 475

скобки, не участвовавшие в совпадении, 533

скорость поиска, 229

следующая строка, 144

слияние модификаторов, 99 смещение

preg_match, 536

начальной позиции, 297 текущей позиции

контроль, 269

совпадение точки со всеми символами, режим, 146

совпадения, механика, побочные эффекты, Perl, 67

создание «лексеров», 380

сокращение затрат на компиляцию, 419 сокращенные обозначения символов,

151

соответствие, определение термина, 53 Спенсер Генри (Henry Spencer), 120, 232

специальные символы, 321

списковый контекст, 356, 374 способы установки только одной

границы области, 460 ссылки, поиск совпадений, 253 стандартные оптимизации, 294 строки

С#, 137

Emacs, 135

Java, 137

РНР, 137

Python, 138

Tcl, 139

VB.NET, 137

как регулярные выражения, 135, 369 в апострофах, PHP, 525

в кавычках

makudonarudo, пример, 210, 282 окончательное регулярное

выражение, 322

раскрутка цикла, 327

убедительный пример, 275 поддержка экранированных

кавычек, 247

и логическая строка, 97 строки продолжения, 226, 235

пример, 330 строки символов

исключение по первому символу, 302


предварительная проверка обязатель- ных символов, оптимизация, 300

сущность

атомарной группировки, 217 максимализма, минимализма

и возврата, 215


Т

теги

HTML, пример, 51

XML, 570

без вложенных элементов, 570 текст в ограничителях, 246 текущая позиция, 447

Java, 478

теория и практика НКА, 228 титульный регистр, 146

Томпсон Кен (Thompson Ken), 147 точка, 156

в сравнении с символьными классами, 156

введение, 35

механика поиска совпадений, 193 традиционный НКА

проверка типа механизма, 190


У

«у каждой задачи есть несколько решений», 417

удаление пропусков, 250

Ульман Джеффри (Jeffrey Ullman), 228 Уолл Ларри (Larry Wall), 120, 434

упорядоченный выбор, 223

проблемы, 224

управление поиском совпадения, 337 управляющие символы, 155 упрощение квантификаторов,

оптимизация, 303

ускорение операций, 294

условные конструкции, 182 во встроенном коде, 402

во встроенных регулярных выражениях, 393

с использованием позиционной проверки, 183

условные проверки

.NET, 486

учет длины текста, оптимизация, 301, 303

учет необходимых элементов, оптимизация, 308


Ф

функции, имеющие отношение к регу- лярным выражениям в Perl, 346

функциональный интерфейс механизма preg, 524

функция обратного вызова, 548, 550


Х

Хейзель Филип (Philip Hazel), 123 хлебные крошки, аналогия, 202 холодная виртуальная машина, 291 хронометраж, 286

.NET, 487

в языке Java, 289 в языке Perl, 431 в языке PHP, 288

в языке Python, 293 в языке Ruby, 292

в языке Tcl, 293

в языке VB.NET, 291 предварительное копирование, 426


Ч

часовой пояс, PHP, 289

числа с плавающей точкой, пример, 245


Ш

шаблон, аргумент

порядок следования элементов, 546, 549

шестнадцатеричные коды, 155


Э

эквивалентность малых квантификаторов, оптимизация, 308

экранирование, введение, 47

экспоненциальный поиск, 280, 397, 408

обнаружение, 280

описание, 280

предотвращение, 306, 322 с использованием

атомарной группировки, 329 захватывающих квантификато-

ров, 328


эффективность PHP, 566

в Perl, 416

проблемы, 416

и возврат, 227

и объекты регулярных выражений, 422

и правильность, 277


Ю

Юникод

Java, 441, 480

.NET, 484

Perl, 349

PHP, 521, 523

алфавиты, Perl, 349 блоки

Java, 441, 480

.NET, 484

версия 3.1, 144

завершители строк, 442

Java, 442 кодовый пункт

введение, 141

выходящий за пределы U+FFFF, 144

обзор, 141 пропуски и /x, 349

псевдосвойства, Perl

\p(Any}, 349

\p{Assigned}, 349

\p{^…}, 349

\p{…}, 349

\p{Unassigned}, 349

свойства, 159

Java, 441

символы комбинационные, 142


Я

язык

см. также: .NET, C#, Java, MySQL, Perl, procmail, Python, Ruby, Tcl, VB.NET

символьный класс, 34 якорные метасимволы

$, 169

^, 169

в строке, 193

механика поиска совпадений, 193 обзор, 169