Понимание шаблона
У вас есть следующий строковый литерал Java:
// Java string literal
"<A HREF=\"([^\"]+)\"[^>]*>([^<]+?)\\.mp3</A>"
Шаблон, представленный этой строкой при обработке всех escape-последовательностей, таков:
// the regex pattern
<A HREF="([^"]+)"[^>]*>([^<]+?)\.mp3</A>
Теперь давайте разберем этот шаблон на части:
_________ _ _ E________
<A HREF="([^"]+)"[^>]*>([^<]+?)\.mp3</A>
\_____/ \______/
1 2
Итак, части этого регулярного выражения:
<A HREF="
в буквальном соответствии ([^"]+)
, т. Е. Все, кроме двойных кавычек, захваченных в группе 1 "
, сопоставленных буквально [^>]*
, т. Е. Все, кроме >
>
, сопоставленных буквально ([^<]+?)
, т. Е. Все, кроме <
, как можно меньше, захваченных в группе 2 .mp3</A>
, сопоставленных буквально (.
экранируется обратной косой чертой)
Итак, глядя на это, мы можем заметить, что регулярное выражение делает следующие предположения:
- Значение атрибута
href
соответствует части 2;он должен быть заключен в двойные кавычки и сам по себе не может содержать никаких двойных кавычек.Это совпадение фиксируется в группе 1. - Все оставшиеся атрибуты соответствуют части 4.
href
должен быть первым атрибутом, иначе регулярное выражение не будет совпадать. - Часть 6соответствует имени файла, захватывая в группу 2.
- Часть 7 соответствует расширению и сразу после закрывающего элемента.Нежелание части 6, вероятно, не является необходимым.
Синтаксический анализ HTML с помощью регулярных выражений - сложная задача, но, учитывая многочисленные предположения, приведенное выше регулярное выражение кажется способным выполнять работу большую часть времени.
Изменение шаблона
Чередование в регулярных выражениях выполняется с помощью вертикальной черты.Важно понимать его приоритет и то, как группировка может быть полезна.
this|that
соответствует одной из этих двух строк: this|that thing
соответствует одной из следующих двух строк: (this|that) thing
соответствует одной из этих двух строк: "this thing"
"that thing"
(this|that) (thing|stuff)
соответствует одной из этихчетыре строки: "this thing"
"that thing"
"this stuff"
"that stuff"
Таким образом, чтобы разрешить расширение mp3
и ogg
, мы можем изменить mp3
в шаблоне на (mp3|ogg)
.Обратите внимание, что эта группа будет сопоставлять и захватывать расширение в группу 3.
Таким образом, последний шаблон:
<A HREF="([^"]+)"[^>]*>([^<]+)\.(mp3|ogg)</A>
\_____/ \_____/ \_______/
1:url 2:filename 3:ext
В качестве строкового литерала Java это:
"<A HREF=\"([^\"]+)\"[^>]*>([^<]+)\\.(mp3|ogg)</A>"
Приложение
[…]
представляет собой класс символов .Нечто вроде [aeiou]
соответствует одному из строчных гласных.[^…]
является отрицательным классом символов.[^aeiou]
соответствует одному из , кроме строчных гласных.
(…)
- это группа захвата .Позволяет получить строку, с которой он совпал, для последующего извлечения.
*
и +
являются спецификаторами повторения .По умолчанию повторение является жадным (то есть соответствует много , насколько это возможно).?
в +?
делает его неохотным (то есть соответствует нескольким , насколько это возможно).
Обратите внимание, что ?
может также служить необязательным спецификатором повторения в других контекстах.
.
- это метасимвол, который соответствует (почти) любому символу .Поскольку нам нужен буквальный период, мы избегаем его, добавляя двойную косую черту.
Обратите внимание, что шаблон регулярного выражения по умолчанию чувствителен к регистру.В Java вы можете использовать флаг Pattern.CASE_INSENSITIVE
(встраиваемый в шаблон как (?i)
).