在没有关于解析(X)HTML或XML并且询问正则表达式的问题的情况下,SO上没有任何日子.
虽然相对容易想出用于演示此任务的正则表达式的不可行性的示例或用表达概念的表达式集合,我仍然无法在SO上找到为什么在外行人中无法做到这一点的正式解释条款.
到目前为止我在这个网站上找到的唯一正式解释可能非常准确,但对于自学成才的程序员来说也很神秘:
这里的缺陷是HTML是Chomsky Type 2语法(无上下文语法)而RegEx是Chomsky Type 3语法(正则表达式)
要么:
正则表达式只能匹配常规语言,但HTML是无上下文的语言.
要么:
有限自动机(它是正则表达式下面的数据结构)除了它所处的状态之外没有内存,如果你有任意深度的嵌套,你需要一个任意大的自动机,它与有限自动机的概念相冲突.
要么:
常规语言的Pumping引理是你不能这样做的原因.
[公平地说:以上大多数解释链接到维基百科页面,但这些并不比答案本身更容易理解].
所以我的问题是:有人可以提供一个外行人的上述正式解释的翻译,为什么不可能使用正则表达式来解析(X)HTML/XML?
编辑:在读完第一个答案之后,我认为我应该澄清:我正在寻找一个"翻译",它也简要地解释了它试图翻译的概念:在答案的最后,读者应该有一个粗略的想法 - 例如 - "常规语言"和"无语境语法"是什么意思......
真正的现代正则表达式真正识别哪种语言?
每当存在具有反向引用的无限长度捕获组(例如(.*)_\1)时,正则表达式现在匹配非常规语言.但是,就其本身而言,这还不足以匹配诸如S ::= '(' S ')' | ?匹配对的parens的无上下文语言.
递归正则表达式(对我来说是新的,但我确信存在于Perl和PCRE中)似乎至少能识别出大多数CFL.
有没有人在这方面做过或读过任何研究?这些"现代"正则表达的限制是什么?对于LL或LR语法,他们是否严格认可或严格低于CFG?或者是否存在可以被正则表达式识别而不是CFG 而且相反的语言?
非常感谢与相关论文的链接.
我不是在谈论类似XHTML的代码.我正在谈论像这个疯狂的标记,这是完全有效的HTML(!)
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html<head>
<title//
<p ltr<span id=p></span</p>
</>
Run Code Online (Sandbox Code Playgroud)
因此,鉴于SGML注入的巨大复杂性,HTML是一种无上下文的语言吗?这是一种正式的语言吗?用语法?
HTML5怎么样?
我是正式语言概念的新手,所以请耐心等待.是的,我已阅读维基百科的文章;)
我有一个类似模式的长htdoc,继续这样:
<td class="MODULE_PRODUCTS_CELL " align="center" valign="top" height="100">
<table width="100" summary="products"><tr>
<td align="center" height="75">
<a href="/collections.php?prod_id=50">
<img src="files/products_categories50_t.txt" border="0" alt="products" /></a><\br>
</td>
</tr>
<tr>
<td align="center">
<a href="/collections.php?prod_id=50"><strong>Buffer</strong><br />
</a>
<td>
</tr></table>
</td>
Run Code Online (Sandbox Code Playgroud)
在上面的html中我想提取:
collections.php?prod_id=50 files/products_categories50_t.txtBuffer我已经尝试过这段代码,
#!/usr/local/bin/perl
use strict;
use warnings;
my $filename = 'sr.txt';
open(FILENAME,$filename);
my @str = <FILENAME>;
chomp(@str);
#print "@str";
foreach my $str(@str){
if ($str =~/<td class(.*)<a href(.*?)><\/td>/) {
print "*****$2\n";
}
}
Run Code Online (Sandbox Code Playgroud)
此代码是试用版.然而,它只带来最后一次出现,而不是每次出现.为什么?
好吧,我们都知道尝试使用Regex解析HTML 会带来Cthulhu的愤怒.很好.对于你为什么不应该这样做,有一些很好的回应.我接受这些,并且不止一次在问题上发布这些链接.
但是让我们把这个问题放在以下范围内:除了Regex之外,我们没有解析HTML的选项.为什么?没关系. 但是,假设我们的开发者目前想要失去他们对Tony the Pony的想法,并尽可能地做出不可能的事情.如果这让你大吃一惊,那么假设这个问题是理论性的.无论什么漂浮你的船.只考虑用正则表达式解析HTML的想法,即使你不应该.
在这里,我们看到一种声称,它是不可能做到的,至少是完美的.但是@NikiC下面有一个非常明智的评论:
这个答案从错误的参数中得出了正确的结论("用正则表达式解析HTML"这是一个坏主意)("因为HTML不是常规语言").大多数人现在所说的"正则表达式"(PCRE)不仅可以解析无上下文的语法(实际上是微不足道的),而且能够解决上下文敏感的语法(参见https://stackoverflow.com/) a/7434814/1222420)
事实是,即使相当冗长,你也可以使用现代正则表达式来做一些非常强大的事情.但是很多人认为这个问题听起来像是停机问题:你可以尝试,但总会有另一种情况,你的解决方案会破坏.
所以这就是问题,而且它有点像两个部分.
我想从html页面中提取所有锚标签.我在Linux中使用它.
lynx --source http://www.imdb.com | egrep "<a[^>]*>"
Run Code Online (Sandbox Code Playgroud)
但是这没有按预期工作,因为结果包含不需要的结果
<a class="amazon-affiliate-site-name" href="http://www.fabric.com">Fabric</a><br>
Run Code Online (Sandbox Code Playgroud)
我想要的
<a href >...</a>
Run Code Online (Sandbox Code Playgroud)
有什么好办法吗?
我想使用perl reg ex one liner来匹配段落标记的内容.该段落是这样的:
<p style="font-family: Calibri,Helvetica,serif;">Text I want to extract</p>
Run Code Online (Sandbox Code Playgroud)
所以我一直在使用这样的东西:
perl -nle 'm/<p>($.)<\/p>/ig; print $1' file.html
Run Code Online (Sandbox Code Playgroud)
任何想法都赞赏
谢谢