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