【问题标题】:Java vs Javascript Regex problemJava vs Javascript 正则表达式问题
【发布时间】:2009-04-30 23:55:51
【问题描述】:

我的正则表达式有问题:<a.*href=[\"'](.*?)[\"'].*>(.*?)</a>。正如您可能知道的那样,它应该从 HTML 字符串中获取所有链接并返回第 2 组中的链接文本和第 1 组中的链接目标。但我遇到了问题。如果我在 Javascript 中尝试它(使用 http://www.regextester.com/,所有标志都打开),它可以正常工作,但在 Java 中,就像这样:

Pattern myPattern = Pattern.compile("<a.*href=[\"'](.*?)[\"'].*>(.*?)</a>", Pattern.CASE_INSENSITIVE);
Matcher match = myPattern.matcher(htmlData);
while(match.find()) {
 String linkText = match.group(2);
 String linkTarget = match.group(1);
}

我没有得到我期望的所有比赛。使用正则表达式测试器,我得到了更多,它的工作方式与预期完全一样,但使用 Java 版本,每页只有 1 或 2 个链接。
对不起,如果这很明显,但我是正则表达式的新手。
谢谢,
艾萨克·沃勒

编辑:我认为我的正则表达式可能有问题。从这个 Apache indexof 页面看:

<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="Bryan%20Adams%20-%20Here%20I%20Am.mp3">Bryan Adams - Here I Am.mp3</a></td><td align="right">27-Aug-2008 11:48  </td><td align="right">170K</td></tr>
<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="Cars%20-%20Drive.mp3">Cars - Drive.mp3</a></td><td align="right">26-Aug-2008 19:04  </td><td align="right">149K</td></tr>
<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="Cock%20Robin%20-%20When%20Your%20Heart%20Is%20Weak.mp3">Cock Robin - When Your Heart Is Weak.mp3</a></td><td align="right">26-Aug-2008 19:04  </td><td align="right">124K</td></tr>
<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="Colbie%20Caillat%20-%20Bubbly.mp3">Colbie Caillat - Bubbly.mp3</a></td><td align="right">27-Aug-2008 11:49  </td><td align="right">215K</td></tr>

<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="Colbie%20Caillat%20-%20The%20Little%20Things.mp3">Colbie Caillat - The Little Things.mp3</a></td><td align="right">27-Aug-2008 11:49  </td><td align="right">176K</td></tr>
<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="Coldplay%20-%20Violet%20Hill.mp3">Coldplay - Violet Hill.mp3</a></td><td align="right">27-Aug-2008 11:49  </td><td align="right">136K</td></tr>
<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="Corrs%20-%20Radio.mp3">Corrs - Radio.mp3</a></td><td align="right">26-Aug-2008 19:04  </td><td align="right">112K</td></tr>
<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="Corrs%20-%20What%20Can%20I%20Do.mp3">Corrs - What Can I Do.mp3</a></td><td align="right">26-Aug-2008 19:04  </td><td align="right">146K</td></tr>
<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="Counting%20Crows%20-%20Big%20Yellow%20Taxi.mp3">Counting Crows - Big Yellow Taxi.mp3</a></td><td align="right">26-Aug-2008 19:04  </td><td align="right">135K</td></tr>

<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="Curtis%20Stigers%20-%20I%20Wonder%20Why.mp3">Curtis Stigers - I Wonder Why.mp3</a></td><td align="right">26-Aug-2008 19:03  </td><td align="right">213K</td></tr>
<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="Cyndi%20Lauper%20-%20Time%20After%20Time.mp3">Cyndi Lauper - Time After Time.mp3</a></td><td align="right">26-Aug-2008 19:03  </td><td align="right">193K</td></tr>
<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="David%20Bowie%20-%20Absolute%20Beginners.mp3">David Bowie - Absolute Beginners.mp3</a></td><td align="right">26-Aug-2008 19:04  </td><td align="right">155K</td></tr>
<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="Depeche%20Mode%20-%20Enjoy%20The%20Silence.mp3">Depeche Mode - Enjoy The Silence.mp3</a></td><td align="right">26-Aug-2008 19:03  </td><td align="right">230K</td></tr>
<tr><td valign="top"><img src="/icons/sound2.gif" alt="[SND]"></td><td><a href="Dido%20-%20White%20Flag.mp3">Dido - White Flag.mp3</a></td><td align="right">27-Aug-2008 11:48  </td><td align="right">158K</td></tr>

我应该得到:
1: 布莱恩%20亚当斯%20-%20这里%20I%20Am.mp3
2:布莱恩·亚当斯 - 我在这里.mp3
还有更多类似的。使用正则表达式测试器,我得到了我想要的所有结果。使用 Java,我一无所获。

【问题讨论】:

  • 这不是 Java 与 JavaScript 的问题,只是该测试器的一个缺陷:它不允许您指定单行模式(Java 中的 DOTALL 模式)。这就是你的正则表达式在那里“起作用”的原因:你所有的匹配都被文本中的换行符包围,所以它们永远不能匹配多个链接。
  • 谢谢 Alex,我该如何解决这个问题?

标签: java regex


【解决方案1】:

你必须转义反斜杠字符和引号:

Pattern myPattern = Pattern.compile("<a.*href=[\\\"'](.*?)[\\\"'].*>(.*?)</a>", Pattern.CASE_INSENSITIVE);

但是,这可能不是您真正的问题。模式中并不真正需要反斜杠。该模式还有一些其他可能的问题。

您在 href 属性之前使用了贪婪匹配,这意味着它将从该行的第一个链接的开头匹配到该行的最后一个链接的 href 属性。通过将匹配从“.*”更改为“.*?”来使匹配不贪婪。 href 属性之后的匹配也是如此,它必须是非贪婪的,否则它将匹配到该行最后一个链接的末尾。

. 字符不匹配换行符,因此如果链接代码或链接中的文本中有换行符,则链接将不匹配。您可以使用[\W\w] 代替. 来匹配任何字符。

因此,删除反斜杠、使匹配不贪婪并允许换行将使模式:

Pattern myPattern = Pattern.compile("<a[\\W\\w]*?href=[\"'](.*?)[\"'][\\W\\w]*?>([\\W\\w]*?)</a>", Pattern.CASE_INSENSITIVE);

编辑:
我忘了转义字符串中[\W\w] 代码中的反斜杠。

【讨论】:

  • 我认为您使用 3 个斜杠而不是 2 个,但无论如何它都不起作用。对不起。
  • Isaac 说他正在使用 DOTALL 修饰符(以及所有其他修饰符),所以他的点已经匹配换行符。想想看,如果他把这件事排除在外,他​​可能不会发现有什么不对劲;示例文本中的所有链接至少由一个换行符分隔。
【解决方案2】:

句号/通配符匹配是否所有都需要不贪婪?

<a.*?href=[\"'](.*?)[\"'].*?>(.*?)</a>

我不是java开发者,所以不知道模式的转义规则。

【讨论】:

    猜你喜欢
    • 2011-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-27
    • 1970-01-01
    相关资源
    最近更新 更多