Регулярные выражения
Регулярное выражение — шаблон, описывающий набор строк: «только цифры», «слово из букв», «адрес почты». С его помощью проверяют ввод, находят фрагменты текста и заменяют их. В Java шаблон записывают обычной строкой.
matches
Метод matches() проверяет, подходит ли вся строка под шаблон. \d означает любую цифру, а + — «один или больше раз»:
void main() {
IO.println("12345".matches("\\d+"));
IO.println("123a5".matches("\\d+"));
}Результат:
true
falseВ Java-строке обратная косая черта экранируется, поэтому шаблон \d+ записывают как "\\d+".
Основы синтаксиса
Несколько самых нужных элементов шаблонов:
| Элемент | Значение |
|---|---|
\d, \w, \s | цифра, буква или цифра или _, пробельный символ |
[abc], [a-z] | один символ из набора или диапазона |
. | любой символ |
*, +, ? | ноль и больше, один и больше, ноль или один раз |
{3}, {2,4} | ровно 3 раза, от 2 до 4 раз |
void main() {
String code = "[A-Z]{2}-\\d{3}";
IO.println("AB-123".matches(code));
IO.println("ab-123".matches(code));
IO.println("AB-12".matches(code));
}Результат:
true
false
falsereplaceAll
replaceAll() заменяет все фрагменты, подходящие под шаблон. \s+ — один или несколько пробельных символов подряд:
void main() {
String text = "Слишком много пробелов";
IO.println(text.replaceAll("\\s+", " "));
IO.println("Тел: 8-900-123-45-67".replaceAll("\\d", "*"));
}Результат:
Слишком много пробелов
Тел: *-***-***-**-**split по шаблону
split() тоже принимает регулярное выражение. Это позволяет разрезать строку сразу по нескольким разделителям:
void main() {
String tags = "java, kotlin; scala,go";
String[] parts = tags.split("[,;]\\s*");
IO.println(Arrays.toString(parts));
}Результат:
[java, kotlin, scala, go][,;] — запятая или точка с запятой, \s* — любое число пробелов после неё.
Pattern и Matcher
Чтобы найти все совпадения внутри текста, шаблон компилируют в объект Pattern, а затем перебирают находки объектом Matcher. Части шаблона в круглых скобках — группы — можно получить отдельно:
void main() {
String text = "Анна: 30 лет, Олег: 25 лет";
Pattern pattern = Pattern.compile("(\\p{L}+): (\\d+)");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
IO.println(matcher.group(1) + " -> " + matcher.group(2));
}
}Результат:
Анна -> 30
Олег -> 25find() ищет следующее совпадение и возвращает false, когда их больше нет. \p{L} — любая буква, включая кириллицу; \w в Java по умолчанию понимает только латиницу. Классы Pattern и Matcher лежат в пакете java.util.regex: в короткой форме программы он подключён сам, в классической нужен import java.util.regex.*;.
Частая ошибка
split() принимает регулярное выражение, а в нём точка означает «любой символ». Поэтому разбиение по "." даёт пустой массив:
void main() {
String ip = "192.168.0.1";
IO.println(ip.split(".").length);
IO.println(ip.split("\\.").length);
}Результат:
0
4Экранируйте специальные символы: "\\.", "\\|", "\\+". Тот же подвох есть у replaceAll(); если шаблон не нужен, используйте replace().