Closed. This question needs to be more focused. It is not currently accepting answers. Learn more。
想改进这个问题吗更新问题,使其只关注一个问题editing this post。
5年前关闭。
(如果您不耐烦,请跳到下面的摘要部分)
它commonly expressed here on Stack Overflow在显影剂中
试图用正则表达式(regex)解析HTML的社区是
坏主意引用Jeff Atwood of Coding Horror:
因此,虽然我可能尝试使用正则表达式解析HTML,但我知道:
这通常是个坏主意。
除非你有严格的纪律和条件
做,把HTML和正则表达式匹配起来会很快变得疯狂,
正是克楚鲁喜欢它。
我有我认为是好的,理性的,半防御的理由
在这个特定的场景中选择正则表达式。
regex不适合HTML解析的原因
一些原因似乎属于这些类别:
in certain
situations,因为
已知You can't use it to parse arbitrary HTML。
regex不能正确处理无效的html(这只是一个例子吗
#1以上?)是的。
cases where a regular expression wouldn't work,而
正则表达式是“chomsky类型3语法(正则语法)”。
有些时候regex可以进行HTML解析吗?
然而,人们也提到,在某些情况下,HTML is a "Chomsky Type 2 grammar (context free grammar)":
[i]有时候解析一组有限的已知html是合适的。
it's okay to parse a
limited set of known HTML:
我想这和
错误地认为,要求每个琐碎的HTML处理任务都由
全面的分析引擎更重要的是要了解这些工具,
他们的强项和弱点,比屈膝
教条主义。
我不明白:(
我不知道在什么情况下解析html是“合适的”
使用regex,正如上面的两个引号所示。我想是因为我没有
真正理解正则表达式不起作用的情况:
很明显,当HTML甚至无效时regex就不工作了,是吗
正确的?
如果您希望您的输入HTML始终有效呢可以解析吗
然后是正则表达式?
是的,我见过。
不,答案真的没有帮助…Jeff Atwood argues。
我现在提出这个问题是因为我读了一些资料
用于this Stack Overflow question with examples already和this one, in particular, lacks
explanation的代码,它们使用正则表达式来解析
HTML字符串!那么为什么他们使用正则表达式而不是HTML解析器呢为什么
正则表达式在这些情况下不会导致某种不正确的行为?
Ruby ERB源代码
所以这里是Ruby ERB:
def scan_line(line)
line.scan(/(.*?)(<%%|%%>|<%=|<%#|<%|%>|\n|\z)/m) do |tokens|
tokens.each do |token|
next if token.empty?
yield(token)
end
end
end
我已经用下面的代码测试过了,果然,
scan_line
正确标记模板,解析出html和erb标记:
t = <<TEMPLATE
<div>
<% cupcakes.each do |c| %>
<p>Oh boy, another cupcake!</p>
<ul>
<li>Flavor: <%= c.flavor %></li>
<li>Price: <%= c.price %></li>
</ul>
<% end %>
</div>
TEMPLATE
t.split("\n").each do |line|
scan_line(line) { |token| puts token }
end
这将产生以下输出:
<div>
<%
cupcakes.each do |c|
%>
<p>Oh boy, another cupcake!</p>
<ul>
<li>Flavor:
<%=
c.flavor
%>
</li>
<li>Price:
<%=
c.price
%>
</li>
</ul>
<%
end
%>
</div>
jQuery源代码
这里是
jQuery:
define(function() {
// Match a standalone tag
return (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
});
我已经在我的浏览器控制台中测试过了,它似乎只会匹配
纯HTML标记,即没有属性和文本内容的标记。例如:
/^<(\w+)\s*\/?>(?:<\/\1>|)$/.exec('<p>Hello!</p>');
// null
/^<(\w+)\s*\/?>(?:<\/\1>|)$/.exec('<img src="foo.jpg"/>');
// null
/^<(\w+)\s*\/?>(?:<\/\1>|)$/.exec('<img/>');
// ["<img/>", "img"]
/^<(\w+)\s*\/?>(?:<\/\1>|)$/.exec('<img>');
// ["<img/>", "img"]
/^<(\w+)\s*\/?>(?:<\/\1>|)$/.exec('<div></div>')
// ["<div></div>", "div"]
tl;dr摘要
上面的Ruby ERB和jQuery源代码使用regex解析HTML字符串那么为什么他们使用正则表达式而不是html解析器呢?为什么
正则表达式在这些情况下不会导致某种不正确的行为?
如果您可以期望您的输入html始终有效,那么可以解析它吗
用正则表达式?
正如casper在评论中所说,erb使用自己的解析规则处理自己的语言,而不是html,所以这是一个危险的问题。类似地,在您给出的示例中,jquery并不试图解析普通html,只是它的一小部分。
有几种情况下使用regex是合适的如果您可以抛弃所有关于HTML语法和结构的知识,将输入视为一个简单的文本文件,那么regex就可以工作了。
另一个需要考虑的是错误的后果如果您尝试对大量随机HTML文件进行regex,例如用于采样目的,您将得到一些假阳性和一些假阴性匹配但是,如果大多数潜在的匹配是正确的,那可能会给你足够精确的输出。
这让我们回到jquery。示例代码正在处理的htmlish字符串仅由jquery使用。所以比赛要么成功要么失败。如果失败了,客户端代码的开发人员将很明显,因为它不会做开发人员希望它做的事情这同样不适用于一般的HTMLHTML的作者将在浏览器中进行测试,浏览器使用的是解析器,而不是regex,并确定它在该上下文中执行了作者想要的操作如果您的代码以不同的方式处理它,那么您将承担所有误报和漏报的风险。
简单地回答你的最后一个问题,有效性是无关紧要的。
顺便说一下,我怀疑一个成熟的html解析引擎比一个成熟的正则表达式引擎更复杂。只是有时候正则表达式引擎更接近实际。
还有一点值得考虑一下这里的社会背景。我们经常看到有人出现堆栈溢出,说“我正试图用正则表达式处理一些HTML,它不起作用,我卡住了,我如何修复它?”你陷入困境的事实是你应该使用解析器的一个重要线索。