PCRE(php)正则表达式,带+匹配的子模式和带*的子模式没有?

时间:2011-01-31 12:33:20

标签: php regex pcre

我希望在html文档中匹配并捕获所有现有(如果有) <style...</style>块和一个 <body..</body>块内部。 我觉得这很简单,但我碰到了一些奇怪的东西。 这是我对整个正则表达式的猜测:

/(<style[\s\S]+<\/style>)*[\s\S]*<body.*>([\s\S]+)<\/body>/i

结果一无所获。所以我把它拆开了,这些部分都有效:

/(<body.*>([\s\S]+)<\/body>)/i
/(<style[\s\S]+<\/style>)/i

所有这第一行中最奇怪的也是有效的,而第二行结果是空的!

/(<style[\s\S]+<\/style>)+/i
/(<style[\s\S]+<\/style>)*/i

所以,我猜错误是子模式后面的*和+之间的差异。为什么?我该如何解决这个问题?

谢谢!

1 个答案:

答案 0 :(得分:1)

你有四个问题:

首先,您使用正则表达式来解析HTML。

第三,你的匹配太多了:你至少需要让一些量词变得懒惰,我。即使用.*?[\s\S]*?等,或者你的正则表达式会匹配到行尾或文件的所有内容,然后只需要回溯以找到最后一个可能的匹配标记。

第四,你通过在重复的群体中重复群体来为灾难性的回溯做好准备,这两个群体都有无数的方法来匹配相同的文本。

根据我的理解,您希望匹配从第一个<style>标记到最终</body>的所有内容,并捕获所有<style>标记的内容和<body>标签的内容。对?然后尝试

/(<style[\s\S]+<\/style>)[\s\S]*?<body.*?>([\s\S]+)<\/body>/i

要分别捕获每个<style>块,您可以尝试最多四个<style>块:

/(<style[\s\S]+?<\/style>)?\s*(<style[\s\S]+?<\/style>)?\s*(<style[\s\S]+?<\/style>)?\s*(<style[\s\S]+?<\/style>)?\s*<body.*?>([\s\S]+)<\/body>/i

如果<style>块全部相邻且仅由空格分隔。你能明白为什么使用正则表达式不是一个好主意吗?