terranum
28 уровень
Milan

Регулярные выражения в Java

Пост из группы Архив info.javarush.ru
3786 участников
RegEx Регулярное выражение это своего рода шаблон, который может быть применен к тексту (String, в Java). Java предоставляет пакет java.util.regex для сопоставления с регулярными выражениями. Регулярные выражения очень похожи на язык программирования Perl и очень просты в освоении. Регулярное выражение или соответствует тексту (его части) или нет. * Если регулярное выражение совпадает с частю текста, то мы можем найти еe. ** Если регулярное выражение составное, то мы можем легко выяснить, какая часть регулярного выражения совпадает с какой частью текста. Первый пример Регулярное выражение "[a-z] +" соответствует всем строчныем буквам в тексте. [a-z] означает любой символ от a до z включительно, и + означает "один или более" символов. Предположим, что мы поставляем строку "code 2 learn java tutorial ". Как это сделать в Java Во-первых, вы должны составить шаблон: import java.util.regex.*; Pattern p = Pattern.compile(“[a-z]+”); Далее вы должны создать matcher для текста, отправив сообщение на схеме: Matcher m = p.matcher(“code 2 learn java tutorial”); ПРИМЕЧАНИЕ: Ни Pattern ни Matcher не имеют конструкторов, мы создаем их с помощью методов класса Pattern. Pattern Class: Объект класса составляет представление регулярного выражения. Класс Pattern не предусматривает никаких публичных конструкторов. Чтобы создать шаблон, необходимо сначала вызвать один из публичных статических методов, которые затем возвращают объект класса Pattern. Эти методы принимают регулярное выражение в качестве аргумента. Matcher Class: Объект "Искатель" является двигателем, который интерпретирует шаблон и выполняет операции сопоставления с входной строкой. Как и Pattern класс, Matcher не имеет публичных конструкторов. Вы получаете объект Matcher вызовом метода matcher, на объекте класса Pattern. После того как мы выполнили эти шаги, и теперь у нас есть экземпляр класса Matcher m,и теперь мы можем проверить, был найден шаблон или нет, и если да, то в какой позиции, и т.д. m.matches() возвращает true, если шаблон соответствует всей строке, иначе false. m.lookingAt() возвращает true, если шаблон соответствует началу строки, и false в противном случае. m.find () возвращает true, если шаблон совпадает с любой частью текста. Находим совпадение После успешного сопостовления, m.start() вернет индекс первого символа, совпавшего и m.end() вернет индекс последнего совпавшего символа, плюс один. Если была предпринята неудачная попытка и совпадения не нашлось, m.start() и m.end() будут бросать IllegalStateException - Это RuntimeException, так что вам не придется его ловить. Может показаться странным, что m.end() возвращает индекс последнего совпавшего символа плюс один, но это именно то, что требуется большинству методов класса String. - Например, “Now is the time“.substring(m.start(), m.end()) вернет ту же самую строку. Взглянем на код: import java.util.regex.*; public class RegexTest { public static void main(String args[]) { String pattern = "[a-z]+"; String text = "code 2 learn java tutorial"; Pattern p = Pattern.compile(pattern); Matcher m = p.matcher(text); while(m.find()) { System.out.print(text.substring(m.start(), m.end()) + "*"); } } } Output: code*learn*java*tutorial*. Дополнительные методы Если есть совпадение, то - m.replaceFirst(replacement) возвращает новую строку, где первая подстрока, совпавшая с шаблоном будет заменена на replacement - m.replaceAll(replacement) возвращает новую строку, где каждая подстрока, совпавшая с шаблоном будет заменена - m.find(StartIndex) находи следующее соответствие, начиная с указанного индекса - m.reset() сбрасывает шаблон - m.reset(NewText) сбрасывает искатель, и дает ему новый текст (может быть String, StringBuffer или CharBuffer) Синтаксис регулярных выражений ^ Соответствует началу строки. $ Соответствует концу строки. . Соответствует любому одиночному символу, кроме символа новой строки. Использование опции m позволяет ему соответствовать новой строке. [...] Соответствует любой одиночный символ в скобках. [^ ...] Соответствует любому одному символу, не в скобках. \A Начало всю строку. \z Конец всей строки. \Z Конец всей строки, кроме конечного терминатора линии. re* Соответствует 0 или более вхождений предшествующего выражения. re+ Одно или более совпадений предыдущего выражения. re? Соответствует 0 или 1 местонахождению предыдущего выражения. re{n} Соответствует ровно N Количество вхождений предшествующего выражения. re{n,} Соответствует N или более вхождений предшествующего выражения. re{n, m} Матчи по меньшей мере, n и в большинстве m вхождений предшествующего выражения. a|b Соответствует a или b. (re) Группа регулярных выражений и помнящая найденный текст. (?: re) Группы регулярных выражений, не помнящая найденный текст. (?> re) Соответствует независимому шаблону без возвратов. \w Соответствует буквам. \W Соответствует не буквенным символам. \s Соответствует пробелам. Эквивалентно [\t\n\r\f]. \S Не пробельные символы. \d Соответствует цифрам. Эквивалентно [0-9]. \D Соответствует не цифрам. \G Соответствует точки последнего совпадения. \n Соответствует новой строке. \b Совпадает на границе слова. \B Совпадает не на границе слова. \n, \t, etc. Символы новой строки, возврата каретки, вкладки и т.д. \Q Цитата все символы до \ E. \E Заканчивается цитирование начатое с \ Q. Оригинал перевода Отличный туториал Reference - What does this regex mean? Визуализатор для проверки Отличный дебаггер с визуализацией
Комментарии (24)
  • популярные
  • новые
  • старые
Для того, что бы оставить комментарий вы должны авторизоваться
DedZahar32 уровень
10 мая 2017, 15:32
Помогите разобраться!
хочу найти в строке все отдельно стоящие цифры и вывести их через пробел.
Вот код:
String s = " 12 23 34 45 56 fg fg7 5hj dfkjh 59 ";
        String pattern = "\\s\\d+\\s";
        Pattern p = Pattern.compile(pattern);
        Matcher m = p.matcher(s);
        StringBuilder sb2 = new StringBuilder();
        while (m.find()) {
            String nomber;
            nomber = s.substring(m.start()+1, m.end()-1);
            sb2.append(nomber + " ");
        }
        System.out.println(sb2);

Консоль: «12 34 56 59»
Почему не читаются 23 и 45?
Уже сломал всю голову…
aryumin16 уровень, Великий Новгород
10 мая 2017, 16:18
Например, вот так:

String s = " 12 23 34 45 56 fg fg7 5hj dfkjh 59 ";
        String pattern = "(?<!\\w)\\d+(?!\\w)";
        Pattern p = Pattern.compile(pattern);
        Matcher m = p.matcher(s);
        StringBuilder sb2 = new StringBuilder();
        while (m.find()) {
            String nomber;
            nomber = s.substring(m.start(), m.end());
            sb2.append(nomber);
            sb2.append(" ");
        }
        System.out.println(sb2);
DedZahar32 уровень
10 мая 2017, 17:34
Но всё-таки, почему не работает "\\s\\d+\\s"?
Объясните, плз.
aryumin16 уровень, Великий Новгород
10 мая 2017, 17:34
а не читаются они, потому что паттерн захватывает пробел-число-пробел. То есть субстрока заканчивается и начинается на пробелы. find() берет пробелы до и после числа, и следующий find() уже их не видит. Поэтому ваш запрос пропускает часть отдельно стоящих цифр.
aryumin16 уровень, Великий Новгород
10 мая 2017, 17:35
если бы было по два пробела до и после цифр, видимо, сработал бы ваш вариант.
DedZahar32 уровень
14 мая 2017, 22:00
Огромное спасибо! Разобрался!
aryumin16 уровень, Великий Новгород
14 мая 2017, 22:03
супер )
pro_moscow26 уровень, Москва
5 апреля 2017, 13:59
Подскажите, а как пробел на плюс заменить?
vacancy.replaceAll(" ", "+");
не подходит
pro_moscow26 уровень, Москва
5 апреля 2017, 14:26
Спасибо, разобрался
nshumeik23 уровень, Алматы
10 февраля 2017, 10:41
Переводные статьи могут грешить ошибками. Нужно было составить регулярное выражение «не содержит букв». Судя по этой статье \W как раз то, что надо. Оказывается нет. Смотрим документацию на docs.oracle.com — \w — это буквы и цифры [a-zA-Z_0-9], а \W — это не буквы и не цифры. Автор, поправьте.
kototim31 уровень
3 августа 2016, 15:48
Господа, помогите пожалуйста. Пытаюсь написать регулярное выражение так, чтобы вставить после вывода двух строк ещё одну строку.
Пытаюсь создать шаблон таким образом:
result.replaceAll("^$\n^$\n",
                "^$\n" + "^$\n" + "Вставить текст сюда" + "\n");

Похоже я совсем не понимаю принципа. Читаю, читаю, а как-то не откладывается. Надо на конкретных своих примерах разбираться. Ткните пожалуйста носом, как мне написать.
Благодарю.
Написал в итоге вот так, но это какой-то костыль…
String[] textArray = result.split("\n");
        for (int i = 0; i < textArray.length; i++)
        {
            System.out.println(textArray[i]);
            i++;
            if (i > textArray.length-1)
                break;
            System.out.println(textArray[i]);
            System.out.println("Вставить текст сюда");
        }
werru34 уровень, Санкт-Петербург
6 марта 2016, 23:30
в статье ничего нет про модификаторы. А получать ответ в несколько строк без них нельзя
Pattern.CANON_EQ Enables canonical equivalence. When this flag is specified, two characters will be considered to match if, and only if, their full canonical decompositions match. The expression «a\u030A», for example, will match the string "\u00E5" when this flag is specified. By default, matching does not take canonical equivalence into account. Specifying this flag may impose a performance penalty.
Pattern.CASE_INSENSITIVE Enables case-insensitive matching. By default, case-insensitive matching assumes that only characters in the US-ASCII charset are being matched. Unicode-aware case-insensitive matching can be enabled by specifying the UNICODE_CASE flag in conjunction with this flag. Case-insensitive matching can also be enabled via the embedded flag expression (?i). Specifying this flag may impose a slight performance penalty.
Pattern.COMMENTS Permits whitespace and comments in the pattern. In this mode, whitespace is ignored, and embedded comments starting with # are ignored until the end of a line. Comments mode can also be enabled via the embedded flag expression (?x).
Pattern.DOTALL Enables dotall mode. In dotall mode, the expression. matches any character, including a line terminator. By default this expression does not match line terminators. Dotall mode can also be enabled via the embedded flag expression (?s). (The s is a mnemonic for «single-line» mode, which is what this is called in Perl.)
Pattern.LITERAL Enables literal parsing of the pattern. When this flag is specified then the input string that specifies the pattern is treated as a sequence of literal characters. Metacharacters or escape sequences in the input sequence will be given no special meaning. The flags CASE_INSENSITIVE and UNICODE_CASE retain their impact on matching when used in conjunction with this flag. The other flags become superfluous. There is no embedd
joyrider23 уровень
24 января 2016, 20:00
Для тех кто первый раз читает, я бы добавил абзац (пару слов) про экранирующий символ \
olegvasylkov39 уровень
2 октября 2015, 11:13
я думаю что следующую ссылку будет полезно сохранить на заметку каждому
darkraha.com/rus/dic/regexp.php
в частности для решения задачек очень полезное выражение \p{Punct}
bulldorez23 уровень, Тюмень
6 марта 2015, 23:20
Люди, подскажите, как составить, к примеру, такую регулярку. Есть строка. Нужно найти в ней слово «blablabla». Слово может быть в начале, в конце, в середине строки. Глупо будет писать:
Pattern p1 = Pattern.compile("^world ");
 p1 = Pattern.compile(" world$");
p1 = Pattern.compile(" world ");


Как это упростить?)
balu197329 уровень
7 марта 2015, 03:21
Pattern.compile("\\bworld\\b");
alexnjc31 уровень
1 марта 2015, 16:48
Отличный пост, необходимый минимум инфы для быстрого старта с RegExp в одном месте. Спасибо за перевод, побольше бы таких постов.
alexnjc31 уровень
1 марта 2015, 17:11
Из шпаргалок есть такая штука
overapi.com/regex/
А еще есть готовые паттерны для валидации e-mail, телефона, URL адреса сайта и прочих данных.
Talapius20 уровень
21 февраля 2015, 20:28
Рекомендую книгу Джеффри Фридл «Регулярные выражения». Она однозначно стоит потраченного времени! В ней четко описаны некоторые тонкости регулярки, которых нет в документации!
Автору спасибо! Основы регулярки то что нужно!