【问题标题】:Regular expression to match a certain HTML element匹配某个 HTML 元素的正则表达式
【发布时间】:2011-04-21 21:59:45
【问题描述】:
我正在尝试编写一个正则表达式来匹配以下 HTML。
<span class="hidden_text">Some text here.</span>
我正在努力写出匹配它的条件并尝试了以下方法,但在某些情况下它也会选择跨度之后的所有内容。
$condition = "/<span class=\"hidden_text\">(.*)<\/span>/";
如果有人能指出我做错了什么,那就太好了。
【问题讨论】:
标签:
php
regex
html-parsing
pcre
【解决方案1】:
我认为这就是他们所说的可教时刻。 :P 现在让我们比较和对比您自我回答中的正则表达式:
"/<span class=\"hidden_text\">(?<=^|>)[^><]+?(?=<|$)<\/span>/"
...还有这个:
'~<span class="hidden_text">[^><]++</span>~'
PHP 的双引号字符串受内嵌变量 ($my_var) 的插值和用大括号 ({return "foo"}) 包裹的源代码的评估影响。如果您不使用这些功能,最好使用单引号字符串以避免意外。作为奖励,您不必再转义这些双引号。
PHP 允许您使用几乎任何 ASCII 标点字符作为正则表达式分隔符。通过将斜杠替换为 ~,我消除了在结束标记中转义斜杠的需要。
向后看 - (?<=^|>) - 没有做任何有用的事情。它只会在匹配开始标记后立即进行评估,因此前一个字符是 always >。
[^><]+? 很好(假设您不想在内容中允许其他标签),但量词不必勉强。 [^><]+ 不可能超过关闭的 </span> 标签,所以偷偷摸摸是有道理的。事实上,继续用possessive quantifier:[^><]++ 踢门。
就像它之前的后视一样,(?=<|$) 只是占用空间。如果[^><]+ 尽其所能,而下一个字符不是<,则无需前瞻即可告诉您匹配将失败。
请注意,我只是在批评您的正则表达式,而不是修复它;你的正则表达式和我的可能每次都会产生相同的结果。即使您正在使用的 HTML 是完全有效的,它们也有很多可能出错的方法。用正则表达式匹配 HTML 就像抓一只涂了油的猪。
【解决方案2】:
您可能有多个跨度,并且您使用的正则表达式将默认为贪婪模式
使用 PHP 的 DOM Parser 从 HTML 中提取内容要容易得多
【解决方案3】:
您不应该尝试在 HTML 等非常规语言上使用正则表达式。最好使用适当的 HTML 解析器来解析文档。
有关如何使用 PHP 执行此操作的更多信息,请参阅以下问题:
【解决方案4】:
您需要通过在.* 之后添加? 来使用非贪婪选择:
$condition = "/<span class=\"hidden_text\">(.*?)<\/span>/";
注意:如果你需要匹配通用的 HTML,你应该使用像 DOM 这样的 XML 解析器。
【解决方案5】:
$condition = "/<span class=\"hidden_text\">(?<=^|>)[^><]+?(?=<|$)<\/span>/";
我明白了。 ;)