Ограничение жадности в регулярках Java
Регулярные выражения по умолчанию жадные. Это значит, что они захватывают максимальное возможное количество символов. Разберем на примере. Пусть у нас есть вот такая строка:
public class Main {
public static void main(String[] args) {
String txt = "aeeex zzz x kkk";
}
}
В этой строке хотим найти подстроку
'aeeex' по следующему шаблону:
буква 'a', затем любой символ
один или более раз, затем буква 'x':
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
Pattern pattern = Pattern.compile("a.+x");
Matcher matcher = pattern.matcher(txt);
String res = matcher.replaceAll("!");
System.out.println(res);
}
}
Хотя нам нужно получить строку '! zzz
x kkk', выведется строка '! kkk'.
Все дело в том, что наша регулярка ищет
все символы от буквы 'a' до буквы
'x'. Но в нашей строке две буквы
'x'! Из-за жадности получается, что
регулярка ищет до самого последнего икса,
тем самым захватывая не то, что нам было
нужно.
Конечно, зачастую такое поведение нам и требуется. Но конкретно в этом случае нужно отменить жадность и сказать регулярке, чтобы она искала до первого икса. В этом случае следует после оператора повторения поставить знак вопроса:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
Pattern pattern = Pattern.compile("a.+?x");
Matcher matcher = pattern.matcher(txt);
String res = matcher.replaceAll("!");
System.out.println(res);
}
}
Жадность можно ограничивать всем операторам
повторения: и *, и ?, и
{} - вот так: *?, ??
и {}?.
Дана строка:
public class Main {
public static void main(String[] args) {
String txt = "aba accca azzza wwwwa";
}
}
Напишите регулярку, которая найдет все
строки по краям которых стоят буквы
'a', и заменит каждую из них на
'!'. Между буквами 'a' может
быть любой символ (кроме 'a').