当正则表达式遇到 DOM(突然变得不再简单)

发布: (2026年2月26日 GMT+8 18:03)
4 分钟阅读
原文: Dev.to

Source: Dev.to

封面图片:当正则表达式遇到 DOM(并且突然变得不再简单)

目标

  • 支持多词查询
  • 优先匹配完整短语
  • 回退到单个 token 匹配
  • 在 DOM 中高亮结果
  • 跳过

脑中想法:“很简单。直接写个正则就行。”

第一步:构建正则

如果用户搜索:

power shell

我会生成如下模式:

power[\s\u00A0]+shell|power|shell

逻辑

  1. 首先尝试匹配完整短语。
  2. 若失败,则匹配单个 token。

纸面上看很简洁,单独使用时也能工作。

第二步:进入 DOM

现在问题从纯字符串匹配转向 DOM 遍历。

任务

  • 遍历 DOM,同时避免 UI 元素。
  • 跳过 , , , 块。
  • 保持语法高亮。
  • 只替换文本节点,保持 DOM 结构完整。

TreeWalker 可以完成这项工作:

const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
  acceptNode(node) {
    const p = node.parentElement;
    if (!p) return NodeFilter.FILTER_REJECT;

    if (p.closest("code, pre, script, style")) {
      return NodeFilter.FILTER_REJECT;
    }

    return NodeFilter.FILTER_ACCEPT;
  },
});

现在我们不只是应用正则,而是进行受控的 DOM 变更。

第三步:交替问题

即使短语出现在交替的第一位:

phrase|token1|token2

引擎仍然会根据上下文愉快地匹配单个 token(powershellPowerShell)。

面临的挑战

  • 重叠匹配
  • 执行顺序
  • 重置 lastIndex
  • 防止双重变更
  • 防止嵌套 “ 元素

第四步:两遍处理?

我考虑将过程拆分:

  1. 尝试匹配短语。
  2. 若未找到,再尝试 token 匹配。

听起来很简单——直到你意识到第一次遍历可能已经改变了 DOM,需要在两遍之间管理状态。

领悟

  • 正则问题单独来看很容易。
  • DOM 变更问题单独来看也很容易。
  • 两者结合后复杂度呈指数增长。

“简单功能”和“迷你搜索引擎”之间的界限非常微妙。

当前进展

  • 搜索大多数情况下能工作。
  • 高亮已应用。
  • 受保护的块已被跳过。
  • 结构得到尊重。

它还不是完整的浏览器级 Ctrl + F,但核心功能已经具备。

我现在对 DOM 的尊重远高于以前,也深刻体会到让 JavaScript 逻辑在活跃的 DOM 树中可预测运行才是真正的挑战。

收获

  • 正则是确定性的;DOM 是结构化且有状态的。
  • 一旦开始替换文本节点,一切都会变得脆弱。
  • 边缘情况、状态管理以及稳健的变更处理是实现真正可靠功能的关键。
0 浏览
Back to Blog

相关文章

阅读更多 »