需要帮助修改正则表达式

Mik*_*ery 0 java regex

有一天我会擅长正则表达式但是现在......

我正在使用以下表达式解析一个查找MP3文件的HTML页面(可以正常工作):

"<A HREF=\"([^\"]+)\"[^>]*>([^<]+?)\\.mp3</A>"
Run Code Online (Sandbox Code Playgroud)

我现在想要搜索MP3和OGG文件.看起来像一个简单的OR修改(.mp3 || .ogg),但我不太确定我是如何把它放在那里的?有关详细信息,请参阅尝试使用Java正则表解析HTML目录列表中的链接.

pol*_*nts 5

理解模式

您有以下Java字符串文字:

// Java string literal
"<A HREF=\"([^\"]+)\"[^>]*>([^<]+?)\\.mp3</A>"
Run Code Online (Sandbox Code Playgroud)

处理完所有转义序列时,此字符串表示的模式为:

// the regex pattern
<A HREF="([^"]+)"[^>]*>([^<]+?)\.mp3</A>
Run Code Online (Sandbox Code Playgroud)

现在让我们分开这个模式:

_________       _     _        E________
<A HREF="([^"]+)"[^>]*>([^<]+?)\.mp3</A>
         \_____/       \______/
            1              2
Run Code Online (Sandbox Code Playgroud)

所以这个正则表达式的部分是:

  1. <A HREF=" 从字面上看
  2. ([^"]+),即在第1组中捕获的除了双引号之外的所有内容
  3. " 从字面上讲
  4. [^>]*,即一切,但 >
  5. > 从字面上看
  6. ([^<]+?),即<第2组中捕获的尽可能少的东西
  7. .mp3</A>字面上匹配(.由反斜杠转义)

所以看看这个,我们可以观察到正则表达式做出以下假设:

  • 所述href属性值由第2部分相匹配; 它必须用双引号括起来,并且本身不能包含任何转义的双引号.该匹配被捕获到组1中.
  • 任何剩余的属性都与第4部分匹配.href必须是第一个属性,否则正则表达式将不匹配.
  • 第6部分匹配文件名,捕获到组2.
  • 第7部分匹配扩展名,紧接在结束元素之后.第6部分的不情愿可能不是必要的.

使用正则表达式解析HTML是一项棘手的工作,但鉴于众多假设,上述正则表达式似乎能够在大多数时间内完成工作.


修改模式

使用垂直条完成正则表达式的交替.了解其优先级以及分组如何有用非常重要.

  • 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"

所以为了允许mp3ogg扩展,我们可以修改mp3模式中的(mp3|ogg).请注意,此组将匹配并将扩展捕获到组3中.

因此,最终的模式是:

<A HREF="([^"]+)"[^>]*>([^<]+)\.(mp3|ogg)</A>
         \_____/       \_____/  \_______/
          1:url      2:filename   3:ext
Run Code Online (Sandbox Code Playgroud)

作为Java字符串文字,这是:

"<A HREF=\"([^\"]+)\"[^>]*>([^<]+)\\.(mp3|ogg)</A>"
Run Code Online (Sandbox Code Playgroud)

附录

[…]是一个角色类.类似于[aeiou]匹配任何一个小写元音的东西.[^…]是一个否定的角色类.[^aeiou]匹配除小写元音之外的任何东西.

(…)是一个捕获组.它允许稍后检索匹配的字符串.

*+重复符.默认情况下,重复是贪婪(即匹配的越好).在?+?使得它不愿(即比赛的几个越好).

注意,它?也可以在其他上下文中用作可选的重复说明符.

.是一个符合(几乎)任何角色的元字符.因为我们想要一个文字句号,所以我们通过前面的双打来逃避它.

请注意,正则表达式模式默认区分大小写.在Java中,您可能希望使用Pattern.CASE_INSENSITIVEflag((?i)在模式中可嵌入).