Главная · Карта сайта · Поиск · Статьи · Компьютерные курсы · Обучающие программы · Открытые проекты · Веб-программирование · Создание интернет-сайта · Полезные ссылки · Глоссарий · Контакты · Декабрь 09 2016 20:22:45
Последнее опубликованное

Что такое Model-View-Controller
Pattern Model-View-Controller

Как создать свой веб-сайт
Как создать свой сайт в интернете

Разное
Статистика

Регулярные выражения. Прикладной синтаксический анализ


Регулярные выражения. Инструмент эффективных решений...

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

На этом шаге я расскажу о трех таких случаях и начну с самого простого и самого часто встречающегося: с разбора строки параметров, передаваемых программе при ее параметризованном запуске. Далее рассмотрим пример командной строки запуска объекта-команды, а закончим наиболее сложным, но также не выдуманным примером – синтаксическим разбором SQL запроса.

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

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

-параметр1 значение1 –параметр2 значение2 … -параметрN значениеN

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

(?i)^(\s*-(\w+)\s+(\w+\s*))+$

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

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

Запуск объекта-команды

В статье о кастомизации программных продуктов я рассказывал о способе расширения базовой функциональности прикладного программного продукта с использованием динамически подключаемых внешних объектов-команд. Если внешняя команда написана с использованием языка программирования, совместимого с платформой Microsoft .NET Framework и является частью динамически подключаемой библиотеки (dll), то для ее запуска нам необходимо знать имя сборки, имя типа и имя метода. Также, синтаксис строки запуска внешней команды должен поддерживать передачу входных параметров. Приводимый далее пример не включает в себя некоторые тонкости адресации типа в сборке .NET Framework, которые необходимо учитывать, например, в том случае, если тип входит в состав пространства имен не самого верхнего уровня, или пространство имен не совпадает с именем сборки. В качестве примера использован самый простой вариант адресации. Вот синтаксис строки вызова внешней команды:

EXECUTE ИмяСборки.ИмяТипа ИмяМетода[(Параметр1=Значение1, Параметр2=Значение2,…, ПараметрN=ЗначениеN)]

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

^(?i)execute\s+(\w+)\.(\w+)\s+(\w+)(\((((?(?<=\()\s*|\s*,\s*))(\w+)\s*=\s*(\w+))+\s*\))?\s*$

В этом и следующем примере используются повторения одних и тех же фрагментов, разделенных запятыми. Здесь это список параметров. В варианте с SQL – это списки полей, таблиц и условий критерия отбора. Для того чтобы отличать первый элемент от последующих (перед первым элементом ставить запятую не нужно), использована возможность “просмотра назад” и условного перехода. В текущем примере фрагмент (?(?<=\()\s*|\s*,\s*) интерпретируется так: если перед текущим (анализируемым) символом открывающая круглая скобка (?<=\(), то далее могут следовать пробелы (фрагмент до вертикальной черты), иначе пробелы должны быть "разбавлены" одной запятой (фрагмент после вертикальной черты).

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

Изобилие метасимвола \s с квантификатором '*' используется только для того, чтобы ослабить синтаксические ограничения и позволить вставлять пробелы между запятыми, скобками, символом “=” и т.д. При включении в синтаксис передачи параметров круглых скобок следует учитывать, что круглые скобки сами по себе являются метасимволами, и поэтому их нужно включать в регулярное выражение с предшествующей “косой чертой” (слэш): \( и \) - использовать экранирование метасимволов. В данном примере использование модификатора (?i) уже оправдано и позволяет писать слово EXECUTE в любом регистре.

Обработка SQL запроса

Этот пример наиболее сложный, а его реализация встречается довольно редко. Тем не менее, встречается. В статье о применении XML я упоминал о создании кэша наиболее востребованных данных из базы данных на основе XML. Хотелось бы, чтобы работать с таким кешем можно было точно так же, как с любыми другими разделами базы данных, а именно посредством SQL. А для этого придется самостоятельно разбирать конструкции SQL запроса и трансформировать их в XPath запросы. В качестве альтернативного информационного хранилища, конечно, может быть использован и не XML, но саму задачу синтаксического анализа SQL запроса все равно придется решать. Ниже представлен пример регулярного выражения, описывающего синтаксис простейших SQL запросов с инструкцией SELECT. Сразу скажу, что регулярное выражение далеко от совершенства и не учитывает большое количество всяких нюансов, но я и не ставлю сейчас цели учесть все варианты. На данный момент главное – это продемонстрировать возможность решения этой задачи с использованием регулярного выражения в принципе.

Регулярное выражение для синтаксического анализа SQL запроса:

(?i)^select((\s*\*\s*)|((?(?<=select)\s+|\s*,\s*)(\w+\.\w+))+\s+)
     from((?(?<=from)\s+|\s*,\s*)(\w+\s*))+(\s+
     where((?(?<=where)\s+|\s+(and|or)\s+)\w+\.\w+\s*(=|!=|<|<=|>|>=|\slike\s)\s*('(\w|\*)*'|(\w+\.\w+))\s*)+)?$

В этом примере также как и в предыдущем для определения того, должна ли быть запятая в данном месте в списке полей (после слова SELECT), в списке таблиц (после слова FROM) и в списке критериев отбора записей (после слова WHERE) используется условный переход на основании результата “просмотра назад”. Помимо "просмотра назад" (?(?<=фрагмент)да|нет), регулярные выражения предоставляют возможность "просмотра вперед" (?(?=фрагмент)да|нет).

Регулярные выражения. Синтаксический анализ SQL запроса
Синтаксический разбор SQL запроса с использованием регулярного выражения.

Необходимо понимать, что с использованием регулярных выражений вы сможете только установить факт соответствия исходной строки общему синтаксису SQL, но определить корректность самого запроса (имеет ли запрос смысл) можно только в процессе дополнительного анализа результатов синтаксического анализа. Например, установить, что после ключевого слова FROM перечислены именно те таблицы, поля которых используются после SELECT можно только программно, анализируя группы table и table_field. В итоге, решение подобной задачи довольно сложное, но польза от него должна оправдывать все усилия и затраты. В противном случае за ее решение не стоит и приниматься. Пример кода, реализующего синтаксический разбор SQL инструкции SELECT на языке программирования C#, представлен здесь.

Самостоятельно: В целях самообразования и преодоления лени могу предложить составить аналогичное регулярное выражение для инструкций UPDATE, INSERT или DELETE. С их синтаксисом можно познакомиться здесь.

Компьютерные курсы и курсы программирования
Основы программирования

Курс для начинающих программистов на C# и VB.NET.

SQL 25™

Построение SQL запросов и работа с базой данных.

C# Quick Guide™

Программирование на C#. Краткое руководство.

RegEx

Применение регулярных выражений.

Plug-in архитектура

Примеры программной Plug-in архитектуры.

XML и его расширения

Язык разметки XML и его расширения с примерами.

HTML и разметка гипертекста

Языки HTML, XHTML и CSS с примерами разметки.

Основы веб-дизайна

Основы веб-дизайна: решения типовых задач верстки.

Программирование на PHP

Руководство по программированию на PHP для начинающих.

Справочные материалы

Шаблоны проектирования
Каталог шаблонов проектирования программных компонентов.

Рефакторинг кода
Каталог приемов рефакторинга программного кода.

Гость
Имя

Пароль



Забыли пароль?
Запросите новый здесь
.
Coding Craft. Все права защищены © 2011. Проект Инициативного Народного Фронта Образования - ИНФО-проект.