Все, кто хоть немного занимается программированием, сталкивались с проблемой правильности ввода данных. Основная сложность заключается в том, что большинство людей не любят читать справку к программе, не любят по несколько раз проверять введённые данные, зато очень любят быстро нажимать на все кнопки подряд, и громко жаловаться на малейшие ошибки в программе:-).
Регулярные выражения. Зачем они нужны?
Кроме того, существуют объективные причины возникновения ошибок. Например, усталость или некачественно составленная документация.
Все это приводит к тому, что программист вынужден тщательно проверять вводимые данные, и сообщать обо всех ошибках пользователю, объясняя при этом как эту ошибку исправить.
В большинстве случаев данные от пользователя поступают в виде текстовых строк. Т.е. нам нужно преобразовать данные к определённому типу.
И вот здесь все зависит от того, какие именно данные мы хотим получить.
Если нам нужен просто какой-нибудь текст (например, имя пользователя), то проверка достаточно простая:
if(name == null || name.equals("")) { //сообщение об ошибке }
Мы просто убеждаемся, что что-то введено.
Проверить правильность ввода чисел тоже несложно. Можно воспользоваться методами parse
… классов Double
, Integer
и т.п.
Например,
try { int v = Integer. parseInt(inputString); } catch(NumberFormatException err) { // сообщение об ошибке }
Но, есть данные, для которых используется специальная форма записи. Например, адреса eMail, телефонные номера и т.п.
Проверку таких данных выполнить сложнее. Нужно проверять наличие обязательных элементов (например, символ @ в адресе eMail), их взаимное расположение и т.д.
Кроме того, могут возникнуть дополнительные задачи. Например, выделение кода города из телефонного номера.
Конечно, для выполнения таких проверок можно написать специальную функцию, содержащую один или несколько циклов, в которых будет выполняться проверка соответствия строки всем требованиям. Но в этом случае, зачастую, получается, что объем кода, выполняющего эти проверки, составляет, чуть ли не половину всей программу (если не больше).
К счастью, существует ряд методов, позволяющих существенно упростить задачу.
Об одном из них я и хочу рассказать. Этот метод заключается в использовании регулярных выражений (regular expressions).
Никогда о них не слышали? Не страшно. Я уверен, что вы постоянно ими пользуетесь. Например, если вам нужно найти все файлы с расширением mp3, то в программе поиска вы пишите «*.mp3». Это и есть регулярное выражение. В данном случае программа поиска выдаст вам список файлов, у которых имя состоит из любого количества любых символов, после имени идет символ «.», а за ним – «*mp3». Если вы напишите «A*.mp3», то получите список файлов, которые начинаются на букву «A», и имеют расширение «mp3».
Вообще, регулярное выражение представляет собой шаблон, с которым можно сравнивать текстовые строки. В приведённом примере, программа поиска сравнивает все имена файлов с заданным шаблоном, и показывает только те, которые с ним совпали.
Средства Java для работы с регулярными выражениями
В стандартную библиотеку Java входит пакет, специально предназначенный для работы с регулярными выражениями — java.util.regex
.
Эта библиотека может быть использована для выполнения таких задач:
- поиск данных;
- проверка данных;
- выборочное изменение данных;
- выделение фрагментов данных;
- и др..
Получить подробную информацию о библиотеке можно из официальной справки к JavaSDK, размещённой на сайте java.sun.com. Здесь же можно почитать The Java Tutorial (учебное пособие по Java), в котором регулярным выражениям посвящён отдельный урок.
В этой статье я хочу показать примеры использования регулярных выражений для проверки правильности ввода данных, и извлечения фрагментов этих данных.
Основную работу выполняют два класса: Pattern
и Matcher
.
Pattern
– представляет собой сам шаблон, т.е. наше регулярное выражение.
Matcher
– это объект, который выполняет сравнение заданной строки с шаблоном.
Для того чтобы создать объект типа Pattern
нужно воспользоваться его статическим методом
compile(< регулярное выражение >)
или
compile(< регулярное выражение >, <параметры>)
.
Создать Matcher
можно с помощью объекта Pattern
.
Например, так:
Pattern p = Pattern.compile("^\\s+", Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE); Matcher m = p.matcher(inputString);
После этого можно сравнивать шаблон со строкой, выполнять поиск нужных фрагментов и т.д.
Но, прежде всего, давайте разберёмся, как составлять регулярные выражения.
В простейшем случае регулярное выражение представляет собой просто текст, например, «стол». Такое выражение можно использовать для поиска слова «стол» в строке, для замены этого слова на какое-нибудь другое и т.д..
Для создания более сложных выражений используются специальные символы (метасимволы). К ним относятся: ([{\^$|)?*+.
. Эти символы имеют специальное значение, которое зависит от их положения в выражении.
Но, что будет, если мы захотим использовать эти символы в выражении в их обычном значении? Для этого нужно перед этим символом поставить \
.
Внимание: если регулярное выражение записано в программе, а не читается из файла или формы, то необходимо использовать два символа \
подряд (\\
). Вы, конечно, помните, что при обработке строк Java считает символ \
служебным (начало эскейп-последовательности), а для того, чтобы получить просто \
нужно ввести \\
.
Теперь посмотрим, как можно использовать специальные символы при составлении выражений. Наверное, наиболее распространённый символ – это «.
«. Он означает – любой символ. Если поставить справа от символа знак «+
«, то это будет означать, что предыдущий символ может встречаться несколько раз. Поясню сказанное на простых примерах:
выражение «.+
» будет соответствовать любому тексту (один или более любых символов);
«A.+
» – любое выражение, которое начинается на букву «А».
Если мы хотим найти текст с известным расположением в строке, то можно воспользоваться символами:
^
— начало строки
$
— конец строки
С помощью квадратных скобок ([]
) можно задать класс символов. Класс символов задаёт некоторый набор символов, который можно использовать в выражениях. Например, выражение «[кп]от
» соответствует словам «кот» и «пот».
Вот ещё несколько примеров использования классов символов.
[^abc] |
любые символы кроме abc (в данном случае символ ^ используется как отрицание) |
[a-d[m-p]] |
любые символы от a до d и от m до p (по алфавиту) |
[a-z&&[^bc]] |
любые символы от a до z кроме b и c |
Кроме этого существуют, так называемые предопределённые классы. Например,
\d |
означает любую цифру |
\D |
любые символы кроме цифр |
\s | пробельные символы ([ \t\n\x0B\f\r] ) |
\S |
любые символы кроме пробельных |
\w |
любые текстовые символы [a-zA-Z_0-9] (как вы заметили сюда символы русского алфавита не входят, как их включить, я покажу позже) |
\W |
любые не текстовые символы |