Technology Pug
Регулярные выражения в языках программирования — мощный, но сложный в освоении инструмент. Потому неудивительно, что многие откладывают его на потом или стараются использовать по минимуму.
Но это лучший способ обработки текстов, а также метод решения задач, которые связаны с поиском, редактированием, заменой текста в файлах. Потому регулярные выражения стоит знать. Сегодня речь пойдет о регулярных выражениях в популярном кроссплатформенном языке Java.
Содержание
Регулярные выражения в Java — это определенные последовательности символов, с помощью которых можно обрабатывать строки текста по специальным синтаксическими шаблонам.
Пример регулярных выражений выглядит так:
String regex=”java”; // шаблон строки ”java”;
String regex=”\\d{3}”; // шаблон строки из трех цифровых символов; Эта методика позволяет узнать, входит ли определенный символ или их последовательность в строку. Иначе говоря, это методика для обработки строк.
К примеру, она может применяться, если нужно проверить корректность ввода электронной почты. В нем обязательно должен присутствовать символ @, адрес домена, точка после него и доменная зона. То есть система проверяет, чтобы адрес выглядел как «user@gmail.com» (сам адрес без кавычек, разумеется), а не «user.gmail.com» или «user@gmail,com», или даже «user@gmail.com.».
Класс Java, который называется Pattern — это базовое решение для работы с регулярными выражениями в Java. Именно его используют при подключении RegEx в код программы.
Этот класс можно использовать двумя разными способами (методами). Во-первых, это Pattern.matches(). Он применяется для быстрой проверки текста на соответствие заданному регулярному выражению. Но он проверяет только один текст или строку.
Во-вторых, это Pattern.compile() — скомпилированный экземпляр Pattern. Вот его уже можно использовать несколько раз, чтобы составить регулярное выражение для нескольких текстов.
Например:
String regex=”java”; // шаблон строки ”java”;
String regex=”\\d{3}”; // шаблон строки из трех цифровых символов; Еще один класс Java для регулярных выражений — Matcher (java.util.regex.Matcher) — он необходим для поиска нескольких вхождений того или иного набора символов в рамках одного текста, а также применяется для поиска в разных текстах, которые подаются на вход в пределах одного шаблона. В нем есть ряд своих методов, которые используются для работы.
В числе основных отметим такие:
boolean matches(): этот метод возвращает значение true при совпадении строки с шаблоном;boolean find(): этот метод возвращает значение true при обнаружении подстроки, которая совпадает с шаблоном, после чего перейдет к ней;int start(): этот метод возвращает значение индекса соответствия;int end(): используя этот метод, можно получить показатели индекса соответствия;String replaceAll(String str): а вот этот метод выводит значение, которое задается подстрокой str при изменении основной строки.А вот так выглядит пример с использованием Pattern и Matcher:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main (String[] args) {
Pattern pattern1 = Pattern.compile ("[x-z]+");//Поиск будет происходить от x до z включительно.
//Поиск будет происходить только по символам нижнего регистра.
//Чтобы отключить чувствительность к регистру, можно использовать Pattern.CASE_INSENSITIVE.
Matcher matcher1 = pattern1.matcher ("x y z 1 2 3 4 ");
System.out.println (matcher1.find()); //Поиск любого совпадения с шаблоном.
//Выводится значение true, так как в строке есть символы шаблона.
Matcher matcher2 = pattern1.matcher ("X Y Z 1 2 3 4");
System.out.println (matcher2.find()); //Выводится значение false.
//Так как в строке нет символов, подходящих по шаблону.
Pattern pattern2 = Pattern.compile ("[a-zA-Z0-9]");
//Добавляется поиск по символам нижнего и верхнего регистра, а также цифр.
Matcher matcher3 = pattern2.matcher ("A B C D X Y Z a b c d x y z 1 2 3 4");
System.out.println (matcher3.find()); //Выводится значение true Еще один класс — PatternSyntaxException. Он выводит сообщение о непроверенном исключении, если в синтаксисе регулярного выражения допущена ошибка. Речь идет о некорректных символах в шаблоне, например, об опечатке.
Класс объявляется вот так:
public class PatternSyntaxException extends IllegalArgumentException
В перечне методов класса отметим такие:
getDescription (): метод получает описание ошибок;int getIndex (): этот метод получает индекс ошибки;getMessage (): в этом методе возвращается многострочная строка, которая содержит описание ошибки, индекс, шаблон с ошибкой и даже визуально показывает, где в шаблоне допущена ошибка;getPattern (): этот метод, в свою очередь, получает ошибочный шаблон регулярного выражения.Пример класса выглядит так:
Live Demo
package com.tutorialspoint;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
public class PatternSyntaxExceptionDemo {
private static String REGEX = "[";
private static String INPUT = "The dog says meow " + "All dogs say meow.";
private static String REPLACE = "cat";
public static void main(String[] args) {
try{
Pattern pattern = Pattern.compile(REGEX);
// get a matcher object
Matcher matcher = pattern.matcher(INPUT);
INPUT = matcher.replaceAll(REPLACE);
} catch(PatternSyntaxException e){
System.out.println("PatternSyntaxException: ");
System.out.println("Description: "+ e.getDescription());
System.out.println("Index: "+ e.getIndex());
System.out.println("Message: "+ e.getMessage());
System.out.println("Pattern: "+ e.getPattern());
}
}
} Для создания регулярного выражения задействуются строки или объекты класса String. Но далеко не каждая строка автоматически может скомпилироваться в регулярное выражение. Она должна быть соответствующим образом написана — с использованием синтаксиса, который определяется в официальных спецификациях Java.
В данном случае речь идет об использовании букв, цифр и метасимволов, которые имеют специальное значение именно в рамках регулярных выражений.
Синтаксические конструкции регулярных выражений, как сказано выше, включают буквенные, цифровые и метасимволы.
Среди них:
Для поиска границ строк, слов и тому подобных данных используются следующие метасимволы:
^ — метасимвол начала обрабатываемой строки;$ — метасимвол окончания обрабатываемой строки;- — так задается метасимвол, который должен быть вне скобок, причем он должен быть только один;\b — таким образом задается окончание слова;\B — так задается условие, когда слово не закончено;\A — так задается старт ввода;\Z — так задается окончание ввода.Также можно выбирать определенные классы символов:
\d — любой цифровой символ;\D — любой нецифровой;\s — символ пробела;\S — символ, не имеющий пробела;. — задать один произвольный символ;\w — буквенно-цифровой символ;\W — любой символ, за исключением буквенно-цифрового.Для задания диапазона можно использовать -, в этом случае регулярное выражение (a-z) будет искать все символы в заданном диапазоне.
В числе других способов использования косой черты отметим:
\n — перенос строки; \\+ — экранирование символа, поскольку косая черта используется в качестве спецсимвола. Подробнее об этом поговорим ниже в соответствующем разделе.Пример самого простого регулярного выражения для проверки адреса электронной почты на правильность выглядит так:
^[A-Z0-9+_.-]+@[A-Z0-9.-]+$
Здесь проверяется вхождение символа @, точки-разделителя и доменной зоны, которые обязательны для электронной почты.
А вот так выглядит более сложный пример, который ищет цифровые символы в строке:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexMatches {
public static void main( String args[] ) {
// Строка для сканирования, чтобы найти шаблон
String str = "Крещение Киевской Руси произошло в 988 году! Не так ли?";
String pattern = "(.*)(\\d+)(.*)";
// Создание Pattern объекта
Pattern r = Pattern.compile(pattern);
// Создание matcher объекта
Matcher m = r.matcher(str);
if (m.find( )) {
System.out.println("Найдено значение: " + m.group(0));
System.out.println("Найдено значение: " + m.group(1));
System.out.println("Найдено значение: " + m.group(2));
}else {
System.out.println("НЕ СОВПАДАЕТ");
}
}
} На выходе получим следующий результат:
Помимо символов, в регулярных выражениях применяются квантификаторы. Это ограничители, с помощью которых задается частота появления определенного символа или нескольких. Их нужно записывать после самих символов.
Основные квантификаторы:
? — символ не появляется вовсе или же появляется всего раз;- — символа вовсе нет в строке или появляется или он появляется более чем 0 раз;+ — символ появляется не менее раза или большее число раз;{n} — символ появляется заданное число раз (n раз);{n,} — символ появляется заданное число раз с условием (n и больше);{n,m} — не меньше n, но не более m раз.Квантификаторы могут функционировать в одном из трех режимов: жадном, сверхжадном и ленивом. Базовый — жадный режим — именно в нем регулярные выражения работают по умолчанию.
В жадном режиме программа будет искать символы максимальной длины, совпадающие в рамках строки. Проход осуществляется сначала слева направо, а затем справа налево.
Сверхжадный режим функционирует сходным образом, но он не использует обратный проход (когда проверка строки идет справа налево) — так называемый реверсивный поиск. Это в некоторых случаях позволяет ускорить процесс.
Ленивый режим ищет самое короткое вхождение совпадающих символов, которое удовлетворяет всем условиям, заданным в поисковом шаблоне.
Давайте перейдем к примерам.
Вот так выглядит жадный режим:
“A.+a”// Ищет максимальное по длине совпадение в строке.
//Пример жадного квантификатора
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main
{
public static void main(String[] args)
{
Pattern p = Pattern.compile("a+");
Matcher m = p.matcher("aaa");
while (m.find())
System.out.println("Pattern found from " + m.start() +
" to " + (m.end()-1));
}
} На выходе будет следующее:
Pattern found from 0 to 2
Сверхжадный режим:
"А.++а"?// Работает также как и жадный режим, но не производит реверсивный поиск при захвате строки.
// Пример сверхжадного квантификатора
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main
{
public static void main(String[] args)
{
Pattern p = Pattern.compile("a++");
Matcher m = p.matcher("aaa");
while (m.find())
System.out.println("Pattern found from " + m.start() +
" to " + (m.end()-1));
}
} На выходе будет следующее:
Pattern found from 0 to 2
Ленивый режим:
“A.+?a”// Ищет самое короткое совпадение.
//Пример ленивого квантификатора
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main
{
public static void main(String[] args)
{
Pattern p = Pattern.compile("g+?");
Matcher m = p.matcher("ggg");
while (m.find())
System.out.println("Pattern found from " + m.start() +
" to " + (m.end()-1));
}
} Вывод будет таким:
Pattern found from 0 to 0 Pattern found from 1 to 1 Pattern found from 2 to 2
В этом разделе мы рассмотрим некоторые примеры, которые помогут понять, как все это работает на деле.
Ранее мы упоминали, что один из базовых примеров — проверка адреса электронной почты на валидность и корректность. То есть чтобы стоял символ @, точка и доменная зона.
Вот так эта проверка выглядит в коде:
List emails = new ArrayList();
emails.add("name@gmail.com");
//Неправильный имейл:
emails.add("@gmail.com");
String regex = "^[A-Za-z0-9+_.-]+@(.+)$";
Pattern pattern = Pattern.compile(regex);
for(String email : emails){
Matcher matcher = pattern.matcher(email);
System.out.println(email +" : "+ matcher.matches());
}
Результат:
name@gmail.com : true
@gmail.com : false Это регулярное выражение проверяет валидность номера телефона. Выглядит оно так:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ValidatePhoneNumber {
public static void main(String[] argv) {
String sPhoneNumber = "605-8889999";
// String sPhoneNumber = "605-88899991";
// String sPhoneNumber = "605-888999A";
Pattern pattern = Pattern.compile("\d{3}-\d{7}");
Matcher matcher = pattern.matcher(sPhoneNumber);
if (matcher.matches()) {
System.out.println("Phone Number Valid");
}
else
{
System.out.println("Phone Number must be in the form XXX-XXXXXXX");
}
}
} А вот класс для определения валидности IP-адреса, записанного в десятичном виде:
private static boolean checkIP(String input) {
return input.matches("((0|1\\d{0,2}|2([0-4][0-9]|5[0-5]))\\.){3}(0|1\\d{0,2}|2([0-4][0-9]|5[0-5]))");
} По правилам, количество открытых скобок должно совпадать с количеством закрытых, поскольку в ином случае нарушается логика работы. Это проверяется так:
private static boolean checkExpression(String input) {
Pattern pattern = Pattern.compile("\\([\\d+/*-]*\\)");
Matcher matcher = pattern.matcher(input);
do {
input = matcher.replaceAll("");
matcher = pattern.matcher(input);
} while (matcher.find());
return input.matches("[\\d+/*-]*");
} Теперь попробуем извлечь дату из строки. Это делается следующим образом:
private static String[] getDate(String desc) {
int count = 0;
String[] allMatches = new String[2];
Matcher m = Pattern.compile("(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)\\d\\d").matcher(desc);
while (m.find()) {
allMatches[count] = m.group();
count++;
}
return allMatches;
} Проверка:
public static void main(String[] args) throws Exception{
String[] dates = getDate("coming from the 25/11/2020 to the 30/11/2020");
System.out.println(dates[0]);
System.out.println(dates[1]);
} Результат:
25/11/2020 30/11/2020
Как видим, регулярные выражения Java широко используются и позволяют реализовывать проверки на корректность данных на лету, хотя многие программисты не любят их из-за сложности. Но в умелых руках это мощное средство для поиска данных, работы со строками и так далее.
Также ознакомиться с регулярными выражениями можно в видео:
На фоне роста спроса на ликвидность в бычьем рынке 2025 года, криптозаймы снова выходят на…
Прокси (proxy), или прокси-сервер — это программа-посредник, которая обеспечивает соединение между пользователем и интернет-ресурсом. Принцип…
Согласитесь, было бы неплохо соединить в одно сайт и приложение для смартфона. Если вы еще…
Повсеместное распространение смартфонов привело к огромному спросу на мобильные игры и приложения. Миллиарды пользователей гаджетов…
В перечне популярных чат-ботов с искусственным интеллектом Google Bard (Gemini) еще не пользуется такой популярностью…
Скрипт (англ. — сценарий), — это небольшая программа, как правило, для веб-интерфейса, выполняющая определенную задачу.…