RegEx匹配XHTML自包含标签以外的打开标签

html HTML

A米亚

2020-03-13

我需要匹配所有这些开始标签:

<p>
<a href="foo">

但不是这些:

<br />
<hr class="foo" />

我想出了这个,想确保我做对了。我只是捕捉到a-z

<([a-z]+) *[^/]*?>

我相信它说:

  • 找到一个小于,然后
  • 查找(并捕获)az一次或多次,然后
  • 找到零个或多个空格,然后
  • 找到零次或多次贪婪的字符,除了/,然后
  • 寻找大于

我有那个权利吗?更重要的是,您怎么看?

第1567篇《RegEx匹配XHTML自包含标签以外的打开标签》来自Winter(https://github.com/aiyld/aiyld.github.io)的站点

20个回答
凯泡芙Davaid 2020.03.13

尽管为此目的使用正则表达式不适当且无效,但有时正则表达式可以为简单的匹配问题提供快速解决方案,并且在我看来,对于琐碎的工作使用正则表达式并不是那么麻烦。

一篇关于匹配最里面的HTML元素的权威博客文章,这些元素由Steven Levithan撰写。

凯梅 2020.03.13

在我看来,您正在尝试匹配结尾不带“ /”的标签。尝试这个:

<([a-zA-Z][a-zA-Z0-9]*)[^>]*(?<!/)>
Green小宇宙伽罗 2020.03.13

如果您只是想查找这些标签(没有解析的野心),请尝试以下正则表达式:

/<[^/]*?>/g

我在30秒内编写了它,并在此处进行了测试:http//gskinner.com/RegExr/

它与您提到的标签类型匹配,而忽略了您想忽略的标签类型。

飞云小胖 2020.03.13
<\s*(\w+)[^/>]*>

零件说明:

<:起始字符

\s*:标记名称前可能有空格(难看但可行)。

(\w+):标签可以包含字母和数字(h1)。好吧,\w也匹配“ _”,但是我猜并没有伤害。如果好奇,请改用([a-zA-Z0-9] +)。

[^/>]*:除了东西>/直至收盘>

>:关闭 >

无关

对于那些低估正则表达式的人来说,它们仅与正则语言一样强大:

可以将非常规的,甚至不是上下文无关n ba n ba n^(a+)b\1b\1$

反引用FTW

Pro伽罗 2020.03.13

关于用于解析(x)HTML的RegExp方法的问题,对于所有谈到某些限制的人的答案是:您没有受过足够的训练来统治这种强大武器的力量,因为NOBODY在这里谈到了递归

一位与RegExp无关的同事通知了我这个讨论,这肯定不是网络上有关这个古老而又热门话题的第一个讨论。

阅读了一些帖子之后,我要做的第一件事是在该线程中寻找“?R”字符串。第二个是搜索“递归”。
不,圣牛,没有找到匹配的东西。
由于没有人提到解析器所基于的主要机制,所以我很快意识到没人明白这一点。

如果(x)HTML解析器需要递归,则没有递归的RegExp解析器不足以实现此目的。这是一个简单的构造。

正则表达式的黑色艺术是难以掌握,所以也许有,我们离开了,而试图和测试我们的个人解决方案捕获整个网络中,一方面进一步的可能性......好吧,我相信它:)

这是魔术图案:

$pattern = "/<([\w]+)([^>]*?)(([\s]*\/>)|(>((([^<]*?|<\!\-\-.*?\-\->)|(?R))*)<\/\\1[\s]*>))/s";

去尝试一下。
它以PHP字符串编写,因此“ s”修饰符使类包含换行符。
这是我在一月份写的PHP手册示例注释参考

(请注意,在该注释中,我错误地使用了“ m”修饰符;尽管未使用^或$定位符,但它已被RegExp引擎丢弃,但应将其删除)。

现在,我们可以从更明智的角度讨论此方法的局限性:

  1. 根据RegExp引擎的具体实现,递归解析的嵌套模式数量可能有所限制,但这取决于所使用的语言
  2. 尽管损坏的(x)HTML不会导致严重错误,但尚未清理

Anyhow it is only a RegExp pattern, but it discloses the possibility to develop of a lot of powerful implementations.
I wrote this pattern to power the recursive descent parser of a template engine I built in my framework, and performances are really great, both in execution times or in memory usage (nothing to do with other template engines which use the same syntax).

达蒙Jim斯丁 2020.03.13

正如许多人已经指出的那样,HTML不是一种常规语言,因此很难解析。我的解决方案是使用整洁的程序将其转换为常规语言,然后使用XML解析器使用结果。为此有很多不错的选择。我的程序是使用Java和jtidy编写的,将HTML转换为XML,然后通过Jaxen将xpath转换为结果。

神无Tom 2020.03.13

这是一个基于PHP的解析器,它使用一些不合常规的正则表达式来解析HTML。作为该项目的作者,我可以告诉您可以使用正则表达式解析HTML,但是效率不高。如果您需要服务器端解决方案(就像我为wp-Typography WordPress插件所做的那样),则可以使用。

乐Eva 2020.03.13

我以前使用过一个名为HTMLParser的开源工具它旨在以各种方式解析HTML,并且很好地达到了目的。它可以将HTML解析为不同的treenode,并且您可以轻松地使用其API从节点中获取属性。检查一下,看看是否可以帮到您。

猴子阳光 2020.03.13

如果您需要PHP:

PHP DOM 功能,除非它是格式正确的XML将无法正常工作。无论它们对全人类的使用有多好。

simplehtmldom很好,但是我发现它有点bug,而且它的内存占用很大[将在大页面上崩溃。]

我从未使用过querypath,因此无法评论其有用性。

另一个可以尝试的是我的DOMParser,它对资源非常少,并且我已经很开心地使用了一段时间。简单易学,功能强大。

对于Python和Java,发布了类似的链接。

对于下注者-我仅在XML解析器证明无法承受实际使用时编写类。宗教否决只会阻止发布有用的答案-请使问题保持​​在问题的角度之内。

小胖Gil 2020.03.13

您要第一个>不带/这里了解如何做到这一点的详细信息。这被称为否定性回溯。

但是,<bar/></foo>该示例的简单实现最终将在此示例文档中匹配

<foo><bar/></foo>

您能否提供更多有关您要解决的问题的信息?您是否以编程方式遍历标签?

猴子猿 2020.03.13

尝试:

<([^\s]+)(\s[^>]*?)?(?<!/)>

它与您的相似,但是最后一个>不能在斜杠之后,并且也可以接受h1

Davaid古一 2020.03.13

我不知道您对此有确切的需求,但是如果您还使用.NET,则不能使用HTML Agility Pack吗?

摘抄:

它是一个.NET代码库,可让您解析“网络外” HTML文件。解析器对“真实世界”格式的HTML非常宽容。

Tony阳光 2020.03.13

W3C以伪正则表达式形式解释了解析:
W3C Link

遵循了var链接QNameS以及Attribute获得更清晰的画面。
基于此,您可以创建一个很好的正则表达式来处理诸如剥离标签之类的事情。

Itachi村村 2020.03.13

中国古代的战略家,一般哲学家孙子说:

据说,如果您认识自己的敌人并认识自己,那么您就可以赢得一百场战斗,而不会遭受任何损失。如果您只了解自己而不是对手,那么您可能会赢或输。如果您既不认识自己,也不认识敌人,那么您将永远危害自己。

在这种情况下,您的敌人是HTML,而您本人或正则表达式。您甚至可能是使用不规则正则表达式的Perl。懂HTML。认识你自己。

我编写了一个描述HTML本质的句。

HTML has
complexity exceeding
regular language.

我还撰写了一个句,描述了Perl中正则表达式的性质。

The regex you seek
is defined within the phrase
<([a-zA-Z]+)(?:[^>]*[^/]*)?>
木心小哥 2020.03.13

虽然您无法使用正则表达式解析HTML的答案是正确的,但它们不适用于此处。OP只想用正则表达式解析一个HTML标记,而这可以用正则表达式来完成。

建议的正则表达式是错误的,但是:

<([a-z]+) *[^/]*?>

如果您向正则表达式添加内容,则可以通过回溯将其强制匹配诸如之类的愚蠢内容<a >>[^/]这太宽松了。另请注意,这<space>*[^/]*是多余的,因为[^/]*还可匹配空格。

我的建议是

<([a-z]+)[^>]*(?<!/)>

(?<! ... )(在Perl正则表达式中)负向查找在哪里它显示为“一个<,然后是一个单词,然后是不是>的任何内容,最后一个可能不是/,后跟>”。

请注意,这允许类似<a/ >(与原始正则表达式一样)的东西,因此,如果您想要更严格的限制,则需要构建一个正则表达式以匹配用空格分隔的属性对。

番长神乐小小 2020.03.13

在shell中,您可以使用sed解析HTML

  1. 图灵赛德
  2. 编写HTML解析器(作业)
  3. ???
  4. 利润!

相关(为什么不应该使用正则表达式匹配):

米亚十三Harry 2020.03.13

我建议使用QueryPath在PHP中解析XML和HTML。它的语法基本上与jQuery相同,只是在服务器端。

Near神奇 2020.03.13

我认为这里的缺点是HTML是Chomsky Type 2语法(无上下文语法),而RegEx是Chomsky Type 3语法(常规语法)由于类型2语法从根本上比类型3语法复杂(请参阅Chomsky层次结构),因此从数学上讲无法使用RegEx解析XML。

但是许多人会尝试,有些甚至会声称成功-但直到其他人发现错误并完全把您弄乱为止。

null 2020.03.13

虽然只有正则表达式的任意 HTML是不可能的,但有时使用它们来解析有限的已知 HTML集合是适当的

如果您想从一小撮HTML页面中抓取数据,然后将它们填充到数据库中,则正则表达式可能会正常工作。例如,我最近想获得我从议会网站上获得的澳大利亚联邦代表的姓名,政党和地区。这是一项有限的一次性工作。

正则表达式对我来说效果很好,并且安装起来非常快。

猿村村 2020.03.13

不要听这些家伙。如果将任务分解成小块,则可以使用regex 完全解析上下文无关的语法。您可以使用按顺序执行每个脚本的脚本来生成正确的模式:

  1. 解决停止问题。
  2. 摆一个圆圈。
  3. 计算O(log n)或以下的旅行商问题。如果不止如此,您将用完RAM,引擎将挂起。
  4. 该模式将非常大,因此请确保您有一个无损压缩随机数据的算法。
  5. 几乎在那里-将整个事情除以零。十分简单。

我本人还没有完成最后一部分,但是我知道我已经接近了。CthulhuRlyehWgahnaglFhtagnException由于某种原因,它总是抛出s,因此我将其移植到VB 6并使用On Error Resume Next一旦调查了刚刚在墙上打开的这扇奇怪的门,我将更新代码。

PS Pierre de Fermat也想出了办法,但是他所写的利润不足以编写代码。

问题类别

JavaScript Ckeditor Python Webpack TypeScript Vue.js React.js ExpressJS KoaJS CSS Node.js HTML Django 单元测试 PHP Asp.net jQuery Bootstrap IOS Android