有一天我会擅长正则表达式,但现在......
我正在解析使用以下表达式查找MP3文件的HTML页面(可以正常工作):
"<A HREF=\"([^\"]+)\"[^>]*>([^<]+?)\\.mp3</A>"
我现在想要搜索MP3和OGG文件。看起来像一个简单的OR修改(.mp3 || .ogg),但我不太确定我是怎么把它放在那里的?有关详细信息,请参阅Trying to parse links in an HTML directory listing using Java regex。
答案 0 :(得分:5)
您有以下Java字符串文字:
// Java string literal
"<A HREF=\"([^\"]+)\"[^>]*>([^<]+?)\\.mp3</A>"
当处理所有转义序列时,此字符串表示的模式为:
// the regex pattern
<A HREF="([^"]+)"[^>]*>([^<]+?)\.mp3</A>
现在让我们分开这个模式:
_________ _ _ E________
<A HREF="([^"]+)"[^>]*>([^<]+?)\.mp3</A>
\_____/ \______/
1 2
所以这个正则表达式的部分是:
<A HREF="
字面匹配([^"]+)
,即除了双引号之外的所有内容,在第1组中捕获"
字面意思[^>]*
,即>
>
字面匹配([^<]+?)
,即第2组中捕获的尽可能少的<
以外的所有内容.mp3</A>
字面匹配(.
通过反斜杠进行转义)所以看看这个,我们可以观察到正则表达式做出以下假设:
href
属性值与第2部分匹配;它必须用双引号括起来,并且本身不能包含任何转义的双引号。此匹配将捕获到组1中。href
必须是第一个属性,否则正则表达式将不匹配。使用正则表达式解析HTML是一件棘手的事情,但是考虑到许多假设,上述正则表达式似乎能够在大多数时间内完成工作。
Alternation是使用垂直条完成的。了解其优先级以及分组如何有用非常重要。
this|that
匹配以下两个字符串中的一个:
"this"
"that"
this|that thing
匹配以下两个字符串中的一个:
"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>"
[…]
是character class。像[aeiou]
这样的东西匹配任何一个小写元音。 [^…]
是否定的字符类。 [^aeiou]
与除了小写元音之外的任何内容匹配。
(…)
是capturing group。它允许稍后检索匹配的字符串。
*
和+
为repetition specifiers。默认情况下,重复是贪婪的(即尽可能匹配多)。 ?
中的+?
使其不情愿(即匹配为少数)。
请注意,?
在其他情境中也可能充当optional repetition specifier。
.
是matches (almost) any character的元字符。由于我们需要一个文字句号,我们通过前面的双打来逃避它。
请注意,正则表达式模式默认区分大小写。在Java中,您可能希望在模式中使用Pattern.CASE_INSENSITIVE
标志(可嵌入为(?i)
)。
答案 1 :(得分:4)
Replace
\.mp3
with
\.((mp3)|(ogg))
请注意使用正则表达式解析HTML。