javascript - 避免 HTML 标记中灾难性的回溯

标签 javascript regex parsing html-parsing

就像我在标题中所说的,我的数据集是标记,它看起来有点像这样

<!DOCTYPE html>
<html>
<head>
    <title>page</title>
</head>
<body>
<main>

<div class="menu">
    <img src=mmayboy.jpg>
    <p> stackoverflow is good </p>
</div>

<div class="combine">
    <p> i have suffered <span>7</span></p>
</div>
</main>
</body>
</html> 

我的正则表达式引擎尝试分别匹配以下每个节点 block ,即我可以尝试匹配combinemenu。一口气,这就是我的正则表达式引擎的样子,尽管我深入了解了它下面的内部结构。

/(<div class="menu">(\s+.*)+<\/div>(?:(?=(\s+<div))))/

它尝试深入该标记并获取所需的节点 block 。就这些。至于内部结构,我们开始吧

/
(
 <div class="menu"> // match text that begins with these literals
  (
   \s+.*
  )+ /* match any white space or character after previous. But the problem is that this matches up till the closing tag of other DIVs i.e greedy. */
  <\/div> // stop at the next closing DIV (this catches the last DIV)
  (?: // begin non-capturing group 
   (?=
    (
     \s+<div
     ) /* I'm using the positive lookahead to make sure previous match is not followed by a space and a new DIV tag. This is where the catastrophic backtracking is raised. */
   )
  )
 )
/

我在其中缩进了注释,以帮助任何愿意提供帮助的人。我还从博客和 the manual 中寻找解决方案他们说这是由具有太多可能性的表达式引起的,可以通过减少结果的机会来补救,即 +? 而不是 * 但作为尽管我已经尽力了,但我无法将其应用于我当前的困境。

最佳答案

(\s+.*)+

可能可以简化为

[^]*?

这应该可以防止灾难性的回溯。整体简化:

/<div class="menu">[^]*?<\/div>/

您是否考虑过使用an HTML parser相反,但是?

var parser = new DOMParser();
var doc = parser.parseFromString(data, 'text/html');
var menu = doc.getElementsByClassName('menu')[0];

console.log(menu.innerHTML);

关于javascript - 避免 HTML 标记中灾难性的回溯,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43082118/

相关文章:

javascript - 如何在 KaTex 中对公式进行装箱?

c# - 正则表达式不接受数字

python - 按年份对 csv 字符串进行分组

javascript - 自动添加类并在菜单关闭或正文点击正文时将其删除

javascript - 使用 coffeescript 生成的 js 未捕获的类型错误

javascript - 什么时候使用 "prototype"这个词来为 javascript 中的对象添加新属性?

php - 在 URL 中添加组名并在没有索引页面的情况下访问该 URL

python - 正则表达式按字面和被动方式匹配换行符

c++ - 有限状态机解析器

java - 解析 ByteBuffer 寻找空格