Регулярни Изрази - Текстова Магия
- Теория
- Код
Регулярни Изрази в Java
Регулярните изрази (regular expressions) са мощен инструмент за работа с текст в програмирането. Те ви позволяват да търсите, замествате и манипулирате текст по сложни и гъвкави начини.
Основни Концепции:
Символи и Метасимволи:
- Обикновени символи: Представляват себе си (например, 'a', '1').
- Метасимволи: Имат специално значение (например,
.
съответства на всякакъв символ,*
означава повторение).
Примери за Метасимволи:
"b."
ще съвпадне с 'b' последван от всякакъв символ (например "ba", "b2")."a*"
съвпада с нула или повече 'a' (например "", "a", "aaa").
Използване на Регулярни Изрази в Java:
Java предоставя класовете Pattern
и Matcher
за работа с регулярни изрази.
Създаване на Pattern:
Pattern шаблон = Pattern.compile("b.");
Търсене на съвпадения с Matcher:
Matcher съвпадение = pattern.matcher("bat");
while (съвпадение.find()) {
System.out.println("Намерено съвпадение: " + съвпадение.group());
}
Квантификатори в Регулярни Изрази:
Квантификаторите са ключови в регулярните изрази. Те определят колко пъти даден елемент трябва да се повтори.
*
(Звездичка): Съответства на нула или повече повторения на предходния елемент.+
(Плюс): Съответства на едно или повече повторения на предходния елемент.?
(Въпросителна): Съответства на нула или едно повторение на предходния елемент.{n}
: Съответства точно наn
броя повторения.{n,}
: Съответства на най-малкоn
броя повторения.{n,m}
: Съответства на междуn
иm
броя повторения.
Примери:
"a*"
съвпада с низове като "", "a", "aa", "aaa"..."a+"
съвпада с "a", "aa", "aaa", но не и с ""."a?"
съвпада с "", "a".
Групи и Групови Операции:
В регулярните изрази, групите позволяват комбинирането на части от израза в единици, които могат да се захващат, заместват или използват за референции.
- Обикновени групи (
()
): Когато части от израза се поставят в скоби, те формират група. Например,(ab)+
съвпада с едно или повече повторения на "ab". - Именувани групи (
(?<name>...)
): Позволяват именуването на групи за по-лесно рефериране. Например,(?<year>\d{4})
дефинира група за година.
Пример с групи:
Pattern шаблон = Pattern.compile("(ab)+");
Matcher съвпадение = шаблон.matcher("ababab");
while (съвпадение.find()) {
System.out.println("Намерено съвпадение: " + съвпадение.group());
}
Операции за Захващане и Заместване:
matcher.group()
: Връща частта от низа, която съвпада с целия шаблон или специфична група.Pattern.matches()
: Проверява дали целият низ съвпада с шаблона.matcher.replaceFirst()
иmatcher.replaceAll()
: Извършват заместване на съвпаденията в низа.
Пример за заместване:
String резултат = "abc123".replaceAll("\\d", "*");
System.out.println(резултат); // Извежда "abc***"
Специфични Символни Класове:
\\d
: Съвпада с всяка цифра.\\w
: Съвпада с всяка буква, цифра или подчертавка.\\s
: Съвпада с всякакви пробелни символи.
Допълнителни Концепции в Регулярни Изрази:
Позитивни и Негативни Предпоставки (Lookaheads and Lookbehinds):
- Позитивна Предпоставка (Lookahead):
(?=pattern)
- съвпада, ако следващата част от текста отговаря на 'pattern'. - Негативна Предпоставка (Negative Lookahead):
(?!pattern)
- съвпада, ако следващата част от текста не отговаря на 'pattern'.
Нежадни Квантификатори (Non-Greedy Quantifiers):
*?
,+?
,??
: Тези нежадни квантификатори търсят най-малкото възможно съвпадение, вместо най-голямото (както правят техните жадни версии).
Пример за нежадни квантификатори:
Pattern шаблон = Pattern.compile("<.*?>");
Matcher съвпадение = шаблон.matcher("<a><b><c>");
while (съвпадение.find()) {
System.out.println("Намерено съвпадение: " + съвпадение.group());
}
// Изведе всяка етикета поотделно, например <a>, <b>, <c>
Гранични Съвпадения (Boundary Matchers):
^
и$
: Съответстват с началото и края на реда.\\b
: Съответства на граница на дума.\\B
: Съответства на не-граница на дума.
Флагове на Регулярни Изрази
Флаговете модифицират поведението на регулярните изрази. Някои от основните флагове включват:
Pattern.CASE_INSENSITIVE
: Игнорира разликите между малки и големи букви.Pattern.MULTILINE
: Променя поведението на ^ и $, така че да съвпадат с началото и края на всеки ред, а не само с началото и края на целия текст.Pattern.DOTALL
: Позволява на . (точка) да съвпада със символи за нов ред.
Пример с флагове:
Pattern шаблон = Pattern.compile("java", Pattern.CASE_INSENSITIVE);
Matcher съвпадение = шаблон.matcher("Java is fun");
System.out.println(съвпадение.find()); // Връща true
Допълнителни Методи и Техники:
matcher.lookingAt()
: Проверява дали частта на началото на низа съвпада с шаблона.Escape символи
: Важно е да се знае как да се "избяга" (escape) специални символи, когато искаме те да бъдат разглеждани като обикновени символи, например чрез използването на \.
Пример за използване на escape символи:
Pattern шаблон = Pattern.compile("\\$\\d+"); // Търси съвпадения като "$100"
Matcher съвпадение = шаблон.matcher("Цената е $100");
System.out.println(съвпадение.find()); // Връща true
За да направим лекцията още по-пълна и да обхванем всички аспекти на регулярните изрази в Java, можем да добавим следните теми:
Backreferences в Регулярни Изрази:
- Backreferences: Те се използват за съвпадение с част от низа, която вече е била захваната по-рано. Backreferences се създават чрез запазване на текст в групи със скоби и се реферират чрез
\n
, къдетоn
е номерът на групата.
Пример за backreferences:
Pattern шаблон = Pattern.compile("(\\b\\w+) \\1");
Matcher съвпадение = шаблон.matcher("hello hello");
System.out.println(съвпадение.find()); // Връща true, защото "hello" се повтаря
Шаблони за Характерни Класове:
- Характерни класове (
[...]
): Те позволяват дефинирането на собствени множества от символи, които да съвпадат. Например,[abc]
съвпада с всяко 'a', 'b', или 'c'.
Пример за характерни класове:
Pattern шаблон = Pattern.compile("[a-c]");
Matcher съвпадение = шаблон.matcher("bravo");
while (съвпадение.find()) {
System.out.println("Намерено съвпадение: " + съвпадение.group());
}
// Изведе "b" и "a"