遇到特定的正则表达式语句问题

时间:2013-11-13 15:44:51

标签: regex expresso

我正在尝试为Woofy编写一个脚本(tl;是一个下载webcomics的程序),但显然我的正则表达式找不到上一页的链接是不行的,据Expresso说。我正试图找到类似的东西:

<a href="http://70-seas.com/?p=1253" title="Prologue 01" class="previous-comic-link"><span>&lsaquo; Previous</span></a>

随每个页面而变化,URL和标题会更改为链接到上一页的内容,其中包含:

<a\shref="http://70-seas.com/?p=[0-9]{4}"\stitle="[.]*\s[.]*\s([.]*)?"\sclass="previous-comic-link"><span>&lsaquo;\sPrevious</span></a>

(有时标题有三个单词,有时它们有两个单词。但它们总是将数字作为最后一个单词。)

鉴于我没有任何正则表达式的经验或正式培训,我不知道我做错了什么。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

有几件事需要解决。

首先,看看http://70-seas.com/?p=[0-9]{4}部分。此处/?表示/字符是可选的。匹配您要匹配文字?字符的网址。由于?字符是正则表达式元字符,这使得某些东西成为可选项,因此您需要将其转义以使其与字面匹配。为此,请使用\?。因此,更新的部分变为http://70-seas.com/\?p=[0-9]{4}。您还添加了expresso标记,因此您可以遍历模式树并发现此问题。

接下来,真正的问题在于这一部分:title="[.]*\s[.]*\s([.]*)?"。正则表达式中的方括号表示与内部任何字符匹配的字符类。 [.]实际上意味着“匹配'。'性格“这不是你的意图。您可能希望使用匹配任何字符的.元字符,但最后通过将其放在字符类中来完全匹配它。接下来,当您可能要在最后一个可选组中包含\s时,您将第三部分设为可选。考虑到这些要点,您应该使用:title=".*\s.*(\s.*)?"

那应该有用。但是,它不是最好的正则表达式,使用.*对我来说通常是一个红旗。 .匹配任何字符,它是一种贪婪的模式,可能会消耗超过预期的数量。最好尝试具体。如果要匹配字母数字字符,请改用\w。根据您的描述,您需要1-3个单词。这可以表示为\w+(?:\s\w+){0,2}。更清洁,更容易理解。它表示我们匹配一个或多个字母数字字符,后跟一个(?:\s\w+)的非捕获组,这意味着再次匹配一个空格,然后再匹配一个或多个字母数字字符。最后,我们将{0,2}量词放在组的末尾,以表示我们想要将该组匹配0-2次。如果您不需要捕获,(?:...)语法会使组无法捕获,从而提高性能。

你还应该做的一件事是逃避所有的双引号。根据您使用的内容,它可能会或可能不会产生影响,但通常需要它。所以你的双引号会变成\"

你现在应该有这样的模式:

<a\shref=\"http://70-seas.com/\?p=[0-9]{4}\"\stitle=\"\w+(?:\s\w+){0,2}\"\sclass=\"previous-comic-link\"><span>&lsaquo;\sPrevious</span></a>

这很好,但这可能更简单。每当您必须在双引号之间匹配某些内容时,只要您不需要匹配其中的任何项目以便稍后引用,那么您可以使用title=\"[^"]+\"来简化此操作。 [^"]+部分使用负字符类,由字符类开头的^字符表示。它基本上匹配任何不是双引号的字符。一旦遇到标题末尾的双引号,匹配将终止。无需担心1-3个单词,因为您只想匹配标题的全部内容。

新模式变为:

<a\shref=\"http://70-seas.com/\?p=[0-9]{4}\"\stitle=\"[^"]+\"\sclass=\"previous-comic-link\"><span>&lsaquo;\sPrevious</span></a>