Фильтрация строк с использованием автоматов
Alexander Babaev
Необходимость фильтрации строк
Строки используются очень часто. А применимо к Интернет-программированию можно сказать, что строки используются постоянно. Любой ответ сервера – это строка, запрос клиента – тоже строка. Работа с XML-файлами – это опять работа со строками, пускай и очень формализованная. Поэтому необходимо уметь быстро и эффективно обрабатывать строковые данные. Основная операция, которая используется – это конкатенация (слияние). Она реализована для всего, чего угодно и обычно очень прозрачна. Вторая же операция – это изменение строк. И тут мнения относительно того, что использовать, расходятся.
Стандартные методы фильтрации строк
Для начала вспомним, как происходит работа со строками в обычной программе. Используется несколько методов. Первый можно назвать классическим. В этом случае для получения результата используются стандартные операции поиска, замены, конкатенации и удаления частей строки. Такой метод оправдан для быстрого решения самых простых задач, но как только требуется реализовать что-нибудь более-менее сложное, мгновенно начинаются проблемы. Кроме того, этот способ совершенно не масштабируется и очень сложно изменяется.
Второй метод – использование регулярных выражений (регэкспов). Подробно рассматривать их не имеет смысла, есть отличная книга Дж. Фридла [1], в которой все подробно описано, в том числе и применимо к Java. Достоинства подхода заключаются в том, что регулярные выражения стандартизованы, обладают огромнейшими возможностями и очень компактно записываются. То есть если вы научились использовать регулярные выражения в Perl или PHP, вам ничего не стоит использовать их в Java (хотя все равно приходится каждый раз выяснять нюансы реализации). Самый главный недостаток – сложность, которая произрастает из огромной мощности регулярных выражений. Простые регэкспы может понять даже начинающий программист, но более-менее сложные начинающему уже не по зубам. Регэкспы же, подобные представленному в листинге 1, не поймет никто даже при очень большом желании (в листинге представлена примерно восьмая часть регулярного выражения, предназначенного для проверки корректности e-mail адреса и его соответствия RFC). Впрочем, есть люди, которые «читают» регулярные выражения «с листа». Данный пример не совсем показателен в том смысле, что и программа, выполняющая аналогичную функцию, будет очень и очень сложна. Но есть и гораздо более простые задачи, (примеры таких задач будут рассмотрены ниже), в которых регулярные выражения использовать так же неудобно.
Листинг 1.Часть регулярного выражения, предназначенного для проверки корректности e-mail адреса, соответствия его RFC.
^[ 40t]*(?:([^x80-xffn 15()]*(?:(?:[^x80-
xff]|([^x80-xffn 15()]*(?:[^x80-xff][^x80-
xffn 15()]*)*))[^x80-
xffn 15()]*)*)[ 40t]*)*(?:(?:[^( 40)<>@,;:".[] 00-