Внимание! Это сайт переехал на www.simplecoding.org
Регулярные выражения. Зачем они нужны?
Средства Java для работы с регулярными выражениями
Удаление лишних пробелов
Проверка формата телефонного номера
Разбивка строки на лексемы
Проверка имени и пароля
Проверка формата адреса eMail
Скачать примеры программ
Заключение
Проверка имени и пароля
Теперь рассмотрим более сложный пример. Очень часто от пользователя требуется ввести имя и пароль. При этом нам нужно проследить, чтобы имя состояло хотя бы из двух символов, а пароль отвечал определенным требованиям безопасности. Для этого примера, я задал такие требования:
- длина пароля – минимум 8 символов;
- пароль не должен содержать имя;
- пароль должен содержать цифры и буквы (т.е. минимум одна буквы и одна цифра).
Если задача ясна, то приступим к её решению.
Начнем с имени. Нам нужно убедиться, что имя содержит как минимум два любых символа, кроме
пробелов. Для этого составляем регулярное выражение - "[.[^\\s]]+".
Оно определяет набор допустимых в имени символов (что угодно, кроме пробелов). Тут я хочу сделать
некоторые пояснения. Имя может содержать пробелы, например, "Иван Иванович". Нам нужно проверить,
что имя содержит хотя бы один фрагмент из двух букв. Т.е. чтобы не было имен вроде " а ".
Для этого мы проводим поиск подстроки, соответствующей нашему выражению, и определяем её длину.
Поиск выполняется просто, с помощью метода find() класса
Matcher. А для определения длины, мы используем методы
end() и start() этого же класса.
Эти методы возвращают индексы символов конца и начала подстроки, найденной с помощью последнего
вызова метода find().
В программе соответствующий участок кода может выглядеть примерно так:
Pattern namePattern = Pattern.compile("[.[^\\s]]+", Pattern.UNICODE_CASE); Matcher m = namePattern.matcher(name); m.find(); //проверяем длину имени, если она меньше двух символов - ошибка if((m.end() - m.start()) > 2) { System.out.println("Name: " + name + " - OK"); } else { System.out.println("Name: " + name + " - ERR"); }
Теперь приступим к анализу введенного пароля. Во-первых, он может содержать любые символы. Соответствующее выражение будет таким: ".+". Во-вторых, он не должен содержать имя. Значит, нам нужно попытаться найти имя пользователя внутри пароля. Для этого мы используем само имя в качестве регулярного выражения. В-третьих, пароль должен содержать цифры. Тут тоже все просто: "\\d". В-четвертых, пароль должен содержать буквы. А вот здесь есть одна проблема. Дело в том, что в предопределенный класс "\\w", входят буквы латинского алфавита и цифры. Избавиться от цифр не сложно с помощью простого выражения [^0-9]. Но, ведь пароль может содержать русские символы, а это значит, что нам надо их добавить. Таким образом, у нас получается вот такое выражение: "[\\w[а-я]&&[^0-9]]".
Внимание: если у вас возникли сомнения на счет кодировок, или вы не уверены, что сможете протестировать использование регулярного выражения в многоязычных программах, то, возможно, поиск букв лучше выполнить в цикле, используя метод isLetter(char ch) класса java.lang.Character. Методы этого класса возвращают результат в соответствии с четвертой версией стандарта Unicode.
Итак, начнем проверки. Проверка соответствия пароля первому требованию осуществляется точно так
же, как и проверка имени. На ней я останавливаться не буду.
Проверку второго требования выполняем с помощью метода find().
Если он возвращает true, то значит имя найдено в пароле.
Pattern pasPattern1 = Pattern.compile(name, Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE); m = pasPattern1.matcher(password); if(m.find()) { //сообщение об ошибке }
Здесь при создании pasPattern1 используются два параметра: Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE. CASE_INSENSITIVE означает, что при поиске выражения, регистр символов не будет учитываться. Действительно, если пользователь напишет в пароле свое имя с маленькой буквы, это все равно будет нарушением второго требования. Параметр UNICODE_CASE означает, что сравнение символов без учета регистра будет проводиться в соответствии со стандартом Unicode.
Проверки третьего и четвертого требования также проводятся с помощью метода
find(). Если этот метод не находит цифры или буквы, то выводится
сообщение об ошибке.
Для того чтобы посмотреть работу этих проверок, вы можете
скачать демонстрационную программу.
Проверка формата адреса eMail
Наверное, одной из наиболее распространенных и сложных проверок при создании web приложений, является проверка адреса eMail. Действительно, практически любая форма регистрации требует ввода eMail.
Формат этого адреса должен соответствовать целому ряду правил. Первым идет имя учетной записи, за ним символ "@", после него имя сервера. При этом ни имя учетной записи, ни имя сервера не могут содержать символы "@" и пробел. Имя сервера должно состоять из нескольких частей (минимум двух), разделенных точками. Последняя часть имени сервера – это имя домена первого уровня. Оно может состоять только из букв латинского алфавита.
Таким образом, получается такое регулярное выражение: "([.[^@\\s]]+)@([.[^@\\s]]+)\\.([a-z]+)". Обратите внимания, что каждая часть выражения взята в круглые скобки. Это позволит нам выделить части адреса (имя учетной записи, имя сервера, домен первого уровня). Но об этом чуть позже. Сейчас разберем подробно само регулярное выражение.
В первой части, которая соответствует имени учетной записи, мы объявляем класс символов, в который входят все символы кроме @ и пробела. Знак +, означает, что имя должно состоять из одного или более символов. Далее следует символ @. После него мы определяем класс символов для имени сервера. Этот класс такой же, как и класс для имени учетной записи. После этого обязательно должна идти точка (\\.). А за ней имя домена первого уровня, которое может состоять из букв латинского алфавита ([a-z]+), как минимум одной.
Для проверки соответствия введенной строки нашему регулярному выражению, используем метод matches() класса Matcher. Он возвращает true, если вся строка соответствует регулярному выражению.
Pattern p = Pattern.compile("([.[^@\\s]]+)@([.[^@\\s]]+)\\.([a-z]+)", Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); Matcher m = p.matcher(eMail); if(m.matches()) { //строка соответствует регулярному выражению }
Теперь нам нужно получить имя учетной записи, имя сервера и домен в виде отдельных строк. Для этого можно использовать метод group(номер_группы) класса Matcher. Например, так:
System.out.println("Name: " + m.group(1)); System.out.println("Server: " + m.group(2)); System.out.println("Domain: " + m.group(3));
Группы нумеруются, начиная с 0. Нулевая группа соответствует всему выражению. Первая группа –
выражение в круглых скобках, которые встретились первыми и т.д.. Например, выражение
"as(.+(ttt))" содержит три группы.
Первая - as(.+(ttt))
Вторая - .+(ttt)
Третья – ttt
Скачать демонстрационную программу можно здесь.
Скачать демонстрационные программы:
Удаление лишних пробелов (RemoveSpaces.zip - 0,9кБ)
Проверка формата телефонного номера (CheckPhoneNumber.zip - 1кБ)
Разбивка строки на лексемы (StringTokenizing.zip - 0,8кБ)
Проверка имени и пароля (checkNamePassword.zip - 1,2кБ)
Проверка формата адреса eMail (checkEMail.zip - 0,9кБ)
Заключение
В этой статье показаны только основные возможности использования регулярных выражений. Подробную
информацию о них можно найти в The Java Tutorial и в JDK Documentation,
расположенных на сайте java.sun.com. Кроме этого, о регулярных
выражениях написано множество интересных статей и книг.
Я надеюсь, что эта статья и приведенные в ней примеры помогут в разработке ваших проектов.
Любые вопросы и замечания, вы можете отправлять мне по адресу vova_33@gala.net или оставлять в гостевой книге.
P.S. Регулярные выражения являются очень мощным средством. Но их использование требует некоторой тренировки. Поэтому если у вас не получилось написать нужное выражение с первого раза, попробуйте его максимально упростить, протестировать, затем чуть-чуть усложнить, опять протестировать, и т.д. В конечном итоге, вы получите то, что вам нужно:-).
Предыдущий раздел