Javenue logo

Javenue

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

Информационные технологии

Регулярные выражения в Java и пакет java.util.regex

Регулярные выражения (Regular Expressions) позволяют сопоставлять текст с указанным шаблоном, а также выполнять замену текста. Эти операции осуществляются с помощью универсальных символов, которые специальным образом интерпретируются. Регулярные выражения поддерживаются и используются в большом количестве языков программирования.

В Java тоже есть пакет, который позволяет работать с ними - java.util.regex. В этом туториале:

Краткий обзор пакета java.util.regex

Пакет состоит всего из трех классов: Matcher, Pattern, PatternSyntaxException.

  • Pattern - скомпилированное представление регулярного выражения. Для компиляции нужно вызвать статический метод compile.
  • Matcher - движок, который производит операцию сравнения (match).
  • PatternSyntaxException - указывает на синтаксическую ошибку в выражении.

Последовательность вызова методов при работе с regexp:

Pattern regexp = Pattern.compile("a*b");
Matcher m = regexp.matcher("aaab");
boolean b = m.matches();

Как видно из примера, регулярное выражение сперва должно быть откомпилировано. Результирующий объект может быть использован для создания объекта Matcher на основе java.lang.CharSequence (String). Matcher в свою очередь вызывает метод matches().

Пример валидации e-mail адреса

Регулярные выражения могут быть очень полезны при server- и client-side валидации данных.

Давайте рассмотрим небольшой пример на Java. Допустим, необходимо проверить корректность e-mail адреса.

import java.util.regex.*;

public class TestRegexp {
    public static final Pattern pattern = Pattern.compile
        ("[a-zA-Z]{1}[a-zA-Z\\d\\u002E\\u005F]+@([a-zA-Z]+\\u002E){1,2}((net)|(com)|(org))");

    public static void doMatch(String word) {
        Matcher matcher = pattern.matcher(word);
        System.out.println("Validation for " + word +
                (matcher.matches() ? " passed." : "not passed."));
    }

    public static void main(String[] args) {
        doMatch("c0nst@money.simply.net");
        doMatch("Name.Sur_name@gmail.com");
        doMatch("useR33@somewhere.in.the.net");
    }
}

Последовательность вида [a-zA-Z] указывает на множество, в нашем случае это множество латинских символов в верхнем и нижнем регистрах. {n} говорит о том, что некоторый символ должен встретится n раз, а {n,m} - от n до m раз. Символ \d указывает на множество цифр. "\u002E" и "\u005F" - это символы точки и подчеркивания соответсвенно. Знак плюс после некоторой последовательности говорит о том, что она должна встретится один или более раз. "|" - представление логического "или".

Полное описание всех конструкций можно найти в Java API.

В нашем примере под Pattern будут подходить те e-mail адреса, которые начинаются с буквы, содержат буквы, цифры, точку и подчеркивание до символа "@" и находятся в доменах com, net, org (не более третьего уровня).

А вот и результат выполнения программы:

Validation for c0nst@money.simply.net passed.
Validation for Name.Sur_name@gmail.com passed.
Validation for user33@somewhere.in.the.net not passed.

Естественно в интернете можно найти намного более сложные регулярки для проверки почтового адреса. Главное, чтобы была понятна идея.

Поиск текста можно осуществить с помощью метода Matcher.find(). Например, находим открывающие html теги в тексте:

public class SearchRegexp {
    public static void main(String[] args) {
        Pattern regexp = Pattern.compile("<[a-z]+>");
        Matcher m = regexp.matcher("<a><b-><1><c><d/>");
        while (m.find()) {
            System.out.println(m.group());
        }
    }
}

Метод find устанавливает курсор на следующую цепочку, а получить саму цепочку можно с помощью метода Matcher.group().

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

Замена цепочек в тексте

У класса Matcher для замены текста есть метод replaceAll. Но что если нам надо совершить более гибкую замену. Для этих целей пригодятся методы appendReplacement и appendTail. Кстати, как раз о вызове метода appendTail программисты иногда забывают. Поиск цепочек как и ранее осуществляем методом Matcher.find().

public class ReplaceRegex {
    public static void main(String[] args) {
        StringBuffer buffer = new StringBuffer();

        Pattern regexp = Pattern.compile("<[a-z]+>");
        Matcher m = regexp.matcher("<a><b-><1><c><d/>");
        while (m.find())
            m.appendReplacement(buffer, "text");
        m.appendTail(buffer);

        System.out.println(buffer);
    }
}

В API для обратной совместимости до сих пор используется StringBuffer.

Пока что все. Если есть вопросы и замечания - пишите.



Комментариев: 0

  Выйти

  * для публикации комментариев нужно