Регулярные выражения в Java
Регулярные выражения определяют шаблоны для строк.
Регулярные выражения можно использовать для поиска, редактирования или обработки текста.
Регулярные выражения не ограничены каким-либо конкретным языком, но в каждом языке есть тонкие различия.
Java предоставляет пакет java.util.regex, который содержит классы Pattern и Matcher для обработки операций сопоставления с регулярными выражениями.
Примеры регулярных выражений
Строка на самом деле является простым регулярным выражением. Например,Hello WorldРегулярное выражение соответствует строке "Hello World".
.(точка) также является регулярным выражением. Она соответствует любому одиночному символу, например "a" или "1".
В следующей таблице перечислены некоторые примеры регулярных выражений и их описания:
| Регулярное выражение | Описание |
|---|---|
this is text |
Совпадает со строкой "this is text" |
this\s+is\s+text |
Обратите внимание на ... в строке\s+。 Совпадает с ... после слова "this"\s+Он может сопоставить несколько пробелов, затем сопоставить строку is, а затем\s+сопоставить несколько пробелов и затем продолжить строкой text. Он может сопоставить такой пример: this is text |
^\d+(\.\d+)? |
^ определяет начало \d+ соответствует одной или более цифрам ? делает опцию внутри круглых скобок необязательной \. соответствует "." Примеры, которые могут быть сопоставлены: "5", "1.5" и "2.21". |
Для получения дополнительных сведений о регулярных выражениях можно обратиться к:Регулярные выражения - Учебник
Пакет java.util.regex
java.util.regexЭтот пакет является пакетом в стандартной библиотеке Java, используемым для поддержки операций с регулярными выражениями.
Пакет java.util.regex в основном включает следующие три класса:
-
Класс Pattern:
Объект Pattern — это скомпилированное представление регулярного выражения. Класс Pattern не имеет открытого конструктора. Чтобы создать объект Pattern, необходимо сначала вызвать его открытый статический метод compile, который возвращает объект Pattern. Этот метод принимает регулярное выражение в качестве первого аргумента.
-
Класс Matcher:
Объект Matcher — это механизм, который интерпретирует и выполняет операции сопоставления с входной строкой. Как и Pattern, Matcher также не имеет открытого конструктора. Чтобы получить объект Matcher, необходимо вызвать метод matcher объекта Pattern.
-
PatternSyntaxException:
PatternSyntaxException — это класс непроверяемого исключения, который указывает на синтаксическую ошибку в шаблоне регулярного выражения.
В следующем примере используется регулярное выражениеexample.*чтобы найти строку, содержащуюexample:
Пример
Пример вывода:
Группы захвата
Группы захвата — это способ рассматривать несколько символов как единое целое. Они создаются путём группировки символов внутри круглых скобок.
Например, регулярное выражение (dog) создаёт одну группу, содержащую "d", "o" и "g".
Группы захвата нумеруются путём подсчёта их открывающих круглых скобок слева направо. Например, в выражении ((A)(B(C))) есть четыре такие группы:
- ((A)(B(C)))
- (A)
- (B(C))
- (C)
Вы можете использовать метод groupCount объекта matcher, чтобы узнать, сколько групп имеет выражение. Метод groupCount возвращает значение int, указывающее, сколько групп захвата в данный момент имеет объект matcher.
Существует также специальная группа (group(0)), которая всегда представляет всё выражение. Эта группа не включается в возвращаемое значение groupCount.
Пример
Следующий пример показывает, как найти строки цифр в заданной строке:
Код файла RegexMatches.java:
Приведённый выше пример компилируется и выполняется со следующим результатом:
Found value: This order was placed for QT3000! OK? Found value: This order was placed for QT Found value: 3000 Found value: ! OK?
Синтаксис регулярных выражений
В других языках,\\это означает:Я хочу вставить обычный (литеральный) обратный слэш в регулярное выражение; пожалуйста, не придавайте ему особого значения.
В Java,\\это означает:Я хочу вставить обратный слэш регулярного выражения, чтобы следующий за ним символ имел особое значение.
Следовательно, в других языках (например, Perl) одного обратного слэша\достаточно для эффекта экранирования, тогда как в регулярных выражениях Java нужны два обратных слэша, чтобы они были разобраны как эффект экранирования в других языках. Также можно просто понять, что в регулярных выражениях Java два\\представляют один в других языках\, поэтому регулярное выражение для одной цифры — это\\d, а обычный обратный слэш обозначается с помощью\\。
System.out.print("\\"); // 输出为 \
System.out.print("\\\\"); // 输出为 \\
Символ | Описание |
|---|---|
\ | Обозначает следующий символ как специальный символ, литерал, обратную ссылку или восьмеричную escape-последовательность. Например,nсоответствуетn。\nсоответствует новой строке. Последовательность\\\\соответствует\\ ,\\(соответствует(。 |
^ | Соответствует позиции в начале входной строки. Если у объектаRegExpсвойствоMultilineустановлено, ^ также будет соответствовать позиции после "\n" или "\r". |
$ | Соответствует позиции в конце входной строки. Если у объектаRegExpустановлено свойствоMultiline, $ также будет соответствовать позиции перед "\n" или "\r". |
* | Соответствует предыдущему символу или подвыражению ноль или более раз. Например, zo* соответствует "z" и "zoo". * эквивалентен {0,}. |
+ | Соответствует предыдущему символу или подвыражению один или более раз. Например, "zo+" соответствует "zo" и "zoo", но не соответствует "z". + эквивалентен {1,}. |
? | Соответствует предыдущему символу или подвыражению ноль или один раз. Например, "do(es)?" соответствует "do" или "do" в "does". ? эквивалентен {0,1}. |
{n} | n — неотрицательное целое число. Совпадение ровноnраз. Например, "o{2}" не соответствует "o" в "Bob", но соответствует двум "o" в "food". |
{n,} | n — неотрицательное целое число. Совпадение как минимумn раз. Например, "o{2,}" не соответствует "o" в "Bob", но соответствует всем o в "foooood". "o{1,}" эквивалентен "o+". "o{0,}" эквивалентен "o*". |
{n,m} | mиn— неотрицательное целое число, гдеn <= m. Совпадение как минимумnраз, как максимумmраз. Например, "o{1,3}" соответствует первым трём o в "fooooood". 'o{0,1}' эквивалентен 'o?'. Примечание: нельзя вставлять пробелы между запятой и цифрами. |
? | Когда этот символ непосредственно следует за любым другим квантификатором (*, +, ?, {n}、{n,}、{n,m}), режим сопоставления — "non-greedy". Режим "non-greedy" соответствует самой короткой возможной искомой строке, тогда как режим по умолчанию "greedy" соответствует самой длинной возможной искомой строке. Например, в строке "oooo" "o+?" соответствует только одному "o", тогда как "o+" соответствует всем "o". |
. | Соответствует любому одиночному символу, кроме "\r\n". Чтобы сопоставить любой символ, включая "\r\n", используйте шаблон, например "[\s\S]". |
(pattern) | Соответствуетшаблонуи захватывает совпавшее подвыражение. Вы можете использовать$0…$9свойство, чтобы получить захваченное совпадение из результирующей коллекции "match". Чтобы сопоставить символ скобки ( ), используйте "\(" или "\)". |
(?:pattern) | СоответствуетшаблонуНо это подвыражение, которое не захватывает совпадение, т. е. это незахватывающее совпадение и оно не сохраняет совпадение для дальнейшего использования. Это полезно при объединении частей шаблона с помощью символа "или" (|). Например, 'industr(?:y|ies)' — более экономное выражение, чем 'industry|industries'. |
(?=pattern) | Подвыражение, выполняющее положительный просмотр вперёд, которое сопоставляетшаблонв начальной точке совпавшей строки. Это незахватывающее совпадение, т. е. оно не может захватить совпадение для дальнейшего использования. Например, 'Windows (?=95|98|NT|2000)' соответствует "Windows" в "Windows 2000", но не соответствует "Windows" в "Windows 3.1". Просмотр вперёд не потребляет символы; то есть после совпадения поиск следующего совпадения начинается сразу после предыдущего совпадения, а не после символов, составляющих просмотр вперёд. |
(?!pattern) | Подвыражение, выполняющее отрицательный просмотр вперёд, которое сопоставляет строку, не находящуюся в начальной точкешаблонасовпавшей строки поиска. Это незахватывающее совпадение, т. е. оно не может захватить совпадение для дальнейшего использования. Например, 'Windows (?!95|98|NT|2000)' соответствует "Windows" в "Windows 3.1", но не соответствует "Windows" в "Windows 2000". Просмотр вперёд не потребляет символы; то есть после совпадения поиск следующего совпадения начинается сразу после предыдущего совпадения, а не после символов, составляющих просмотр вперёд. |
x|y | Соответствуетxилиy. Например, 'z|food' соответствует "z" или "food". '(z|f)ood' соответствует "zood" или "food". |
[xyz] | Набор символов. Соответствует любому включённому символу. Например, "[abc]" соответствует "a" в "plain". |
[^xyz] | Отрицательный набор символов. Соответствует любому символу, не входящему в набор. Например, "[^abc]" соответствует "p", "l", "i", "n" в "plain". |
[a-z] | Диапазон символов. Соответствует любому символу в указанном диапазоне. Например, "[a-z]" соответствует любой строчной букве в диапазоне от "a" до "z". |
[^a-z] | Символ отрицательного диапазона. Совпадает с любым символом, не входящим в указанный диапазон. Например, "[^a-z]" соответствует любому символу вне диапазона от "a" до "z". |
\b | Совпадает с границей слова, то есть позицией между словом и пробелом. Например, "er\b" совпадает с "er" в "never", но не совпадает с "er" в "verb". |
\B | Совпадение с не-границей слова. "er\B" совпадает с "er" в "verb", но не совпадает с "er" в "never". |
\cx | Совпадаетxс указанным управляющим символом. Например, \cM совпадает с Control-M или возвратом каретки.xЗначение должно быть в диапазоне A-Z или a-z. Если нет, то c считается самим символом "c". |
\d | Совпадение с цифровым символом. Эквивалентно [0-9]. |
\D | Совпадение с нецифровым символом. Эквивалентно [^0-9]. |
\f | Совпадение с символом подачи страницы. Эквивалентно \x0c и \cL. |
\n | Совпадение с символом новой строки. Эквивалентно \x0a и \cJ. |
\r | Совпадает с возвратом каретки. Эквивалентно \x0d и \cM. |
\s | Совпадает с любым пробельным символом, включая пробел, табуляцию, подачу страницы и т. д. Эквивалентно [ \f\n\r\t\v]. |
\S | Совпадает с любым непробельным символом. Эквивалентно [^ \f\n\r\t\v]. |
\t | Совпадение с символом табуляции. Эквивалентно \x09 и \cI. |
\v | Совпадение с символом вертикальной табуляции. Эквивалентно \x0b и \cK. |
\w | Совпадает с любым словесным символом, включая подчёркивание. Эквивалентно "[A-Za-z0-9_]". |
\W | Совпадает с любым несловесным символом. Эквивалентно "[^A-Za-z0-9_]". |
\xn | Совпадает сn, гдеn— это шестнадцатеричный escape-код. Шестнадцатеричный escape-код должен состоять ровно из двух цифр. Например, "\x41" соответствует "A". "\x041" эквивалентно "\x04"&"1". ASCII-коды допускаются в регулярных выражениях. |
\num | Совпадает сnum, гдеnum— положительное целое число. Обратная ссылка на захваченное совпадение. Например, "(.)\1" соответствует двум последовательным одинаковым символам. |
\n | Определяет восьмеричный escape-код или обратную ссылку. Если перед \nстоит по крайней мереnзахватывающих подвыражений, тоnявляется обратной ссылкой. В противном случае, еслиnявляется восьмеричной цифрой (0-7), тоnявляется восьмеричным escape-кодом. |
\nm | Идентифицирует восьмеричный escape-код или обратную ссылку. Если \nmимеет перед собой по крайней мереnmзахватывающих подвыражений, тоnmявляется обратной ссылкой. Если \nmимеет перед собой по крайней мереnзахватов, тоnявляется обратной ссылкой, за которой следует символm. Если ни один из предыдущих случаев не существует, то \nmсоответствует восьмеричному значениюnm, гдеn иmявляются восьмеричными цифрами (0-7). |
\nml | Когдаnявляется восьмеричной цифрой (0-3),mиlкогда она является восьмеричной цифрой (0-7), соответствует восьмеричному escape-кодуnml。 |
\un | Соответствуетn, гдеn— это символ Unicode, представленный четырёхзначным шестнадцатеричным числом. Например, \u00A9 соответствует символу авторского права (©). |
Согласно требованиям спецификации языка Java, обратные косые черты в строках в исходном коде Java интерпретируются как Unicode-экранирования или другие экранирования символов. Поэтому в строковых литералах необходимо использовать две обратные косые черты, чтобы защитить регулярное выражение от интерпретации компилятором байт-кода Java. Например, при интерпретации как регулярного выражения строковый литерал "\b" соответствует одному символу возврата на одну позицию (backspace), а "\\b" соответствует границе слова. Строковый литерал "\(hello\)" недопустим и вызовет ошибку времени компиляции; чтобы сопоставить строку (hello), необходимо использовать строковый литерал "\\(hello\\)".
Методы класса Matcher
Методы индексов
Методы индексов предоставляют полезные значения индексов, которые точно указывают, где совпадение может быть найдено во входной строке:
| Нет. | Метод и описание |
|---|---|
| 1 |
public int start() Возвращает начальный индекс предыдущего совпадения. |
| 2 |
public int start(int group) Возвращает начальный индекс подпоследовательности, захваченной заданной группой во время предыдущей операции сопоставления. |
| 3 |
public int end() Возвращает смещение после последнего совпавшего символа. |
| 4 |
public int end(int group) Возвращает смещение после последнего символа подпоследовательности, захваченной указанной группой во время предыдущей операции сопоставления. |
Методы исследования
Методы поиска используются для проверки входной строки и возвращают логическое значение, указывающее, найден ли шаблон:
| Нет. | Метод и описание |
|---|---|
| 1 |
public boolean lookingAt() Пытается сопоставить входную последовательность с шаблоном, начиная с начала области. |
| 2 |
public boolean find() Пытается найти следующую подпоследовательность входной последовательности, соответствующую шаблону. |
| 3 |
public boolean find(int start) Сбрасывает этот сопоставитель и затем пытается найти следующую подпоследовательность входной последовательности, соответствующую шаблону, начиная с указанного индекса. |
| 4 |
public boolean matches() Пытается сопоставить всю область с шаблоном. |
Методы замены
Методы замены — это методы для замены текста во входной строке:
| Нет. | Метод и описание |
|---|---|
| 1 |
public Matcher appendReplacement(StringBuffer sb, String replacement) Реализует нетерминальный шаг добавления и замены. |
| 2 |
public StringBuffer appendTail(StringBuffer sb) Реализует терминальный шаг добавления и замены. |
| 3 |
public String replaceAll(String replacement) Заменяет каждую подпоследовательность входной последовательности, соответствующую шаблону, заданной строкой замены. |
| 4 |
public String replaceFirst(String replacement) Заменяет первую подпоследовательность входной последовательности, соответствующую шаблону, заданной строкой замены. |
| 5 |
public static String quoteReplacement(String s) Возвращает литеральную строку замены для указанной строки. Этот метод возвращает строку, которая работает так, как если бы это была литеральная строка, переданная методу appendReplacement класса Matcher. |
Методы start и end
Ниже приведён пример, который подсчитывает, сколько раз слово "cat" встречается во входной строке:
Код файла RegexMatches.java:
Приведённый выше пример компилируется и выполняется со следующим результатом:
Match number 1 start(): 0 end(): 3 Match number 2 start(): 4 end(): 7 Match number 3 start(): 8 end(): 11 Match number 4 start(): 19 end(): 22
Видно, что в этом примере используются границы слов, чтобы гарантировать, что буквы "c", "a", "t" не являются просто подстрокой более длинного слова. Это также даёт полезную информацию о том, где совпадения встречаются во входной строке.
Метод start возвращает начальный индекс подпоследовательности, захваченной данной группой во время предыдущей операции сопоставления, а метод end возвращает индекс последнего совпавшего символа плюс 1.
Методы matches и lookingAt
Оба метода matches и lookingAt используются для попытки сопоставить входную последовательность с шаблоном. Разница в том, что matches требует совпадения всей последовательности, тогда как lookingAt — нет.
Метод lookingAt не требует совпадения всей строки, но требует совпадения начиная с первого символа.
Эти два метода часто используются в начале входной строки.
Мы используем следующий пример, чтобы объяснить эту функциональность:
Код файла RegexMatches.java:
Приведённый выше пример компилируется и выполняется со следующим результатом:
Current REGEX is: foo Current INPUT is: fooooooooooooooooo Current INPUT2 is: ooooofoooooooooooo lookingAt(): true matches(): false lookingAt(): false
Методы replaceFirst и replaceAll
Методы replaceFirst и replaceAll используются для замены текста, соответствующего регулярному выражению. Разница в том, что replaceFirst заменяет первое совпадение, а replaceAll — все совпадения.
Следующий пример поясняет эту функциональность:
Код файла RegexMatches.java:
Результат компиляции и запуска приведенного выше примера:
The cat says meow. All cats say meow.
Методы appendReplacement и appendTail
Класс Matcher также предоставляет методы appendReplacement и appendTail для замены текста:
См. следующий пример, поясняющий эту функциональность:
Код файла RegexMatches.java:
Результат компиляции и запуска приведенного выше примера:
-foo-foo-foo-kkk
Методы класса PatternSyntaxException
PatternSyntaxException — это непроверяемый класс исключения, указывающий на синтаксическую ошибку в шаблоне регулярного выражения.
Класс PatternSyntaxException предоставляет следующие методы, помогающие увидеть, какая ошибка произошла.
| Нет. | Метод и описание |
|---|---|
| 1 |
public String getDescription() Возвращает описание ошибки. |
| 2 |
public int getIndex() Возвращает индекс ошибки. |
| 3 |
public String getPattern() Возвращает ошибочный шаблон регулярного выражения. |
| 4 |
public String getMessage() Возвращает многострочную строку, содержащую описание синтаксической ошибки и её индекс, ошибочный шаблон регулярного выражения и визуальное указание индекса ошибки в шаблоне. |