You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于无HTML原始串索引在含HTML串中精准包裹指定子串?

实现纯文本区间在带HTML标签字符串中的精准样式包裹

核心思路

要解决这个问题,关键是对齐纯文本(rawStr)和带标签文本(htmlStr)的字符位置:先从htmlStr中提取纯文本,和rawStr匹配后,定位目标区间在htmlStr纯文本中的位置;再遍历htmlStr,区分标签与文本内容,跳过标签的同时,将目标区间内的文本用指定样式的<span class="dsa">包裹,保留原有HTML标签。

实现步骤

  1. 提取htmlStr的纯文本:过滤掉所有HTML标签,得到和rawStr一致的纯文本内容,用于位置对齐。
  2. 定位目标区间:根据rawStr的startIndex和endIndex,确定目标文本在htmlStr纯文本中的起始(targetStart)和结束(targetEnd)位置。
  3. 遍历处理htmlStr:使用状态机模式,标记当前是否处于HTML标签内;同时记录当前处理到的纯文本位置,当位置落在[targetStart, targetEnd)区间时,对文本字符进行包裹,遇到标签则直接保留。

代码实现

function wrapTargetInHtml(rawStr, htmlStr, startIndex, endIndex) {
    // 提取htmlStr的纯文本内容
    const htmlPlain = htmlStr.replace(/<[^>]+>/g, '');
    // 校验纯文本一致性(可选,确保输入合法)
    if (htmlPlain !== rawStr) {
        throw new Error('rawStr与htmlStr的纯文本内容不匹配');
    }

    const targetLength = endIndex - startIndex;
    if (targetLength <= 0) return htmlStr;

    let result = '';
    let inTag = false;
    let plainCharCount = 0;
    let inWrap = false;

    for (let i = 0; i < htmlStr.length; i++) {
        const char = htmlStr[i];

        // 处理HTML标签的开始
        if (char === '<') {
            // 若正在包裹文本,先关闭span
            if (inWrap) {
                result += '</span>';
                inWrap = false;
            }
            inTag = true;
            result += char;
            continue;
        }
        // 处理HTML标签的结束
        if (char === '>') {
            inTag = false;
            result += char;
            continue;
        }

        // 处于标签内,直接追加字符
        if (inTag) {
            result += char;
            continue;
        }

        // 处理纯文本字符
        const isInTarget = plainCharCount >= startIndex && plainCharCount < endIndex;
        
        // 进入目标区间且未开启包裹时,打开span
        if (isInTarget && !inWrap) {
            result += '<span class="dsa" style="background-color:red">';
            inWrap = true;
        }
        // 离开目标区间但处于包裹状态时,关闭span
        else if (!isInTarget && inWrap) {
            result += '</span>';
            inWrap = false;
        }

        result += char;
        plainCharCount++;
    }

    // 遍历结束后,若仍处于包裹状态则关闭span
    if (inWrap) {
        result += '</span>';
    }

    return result;
}

// 测试示例
const rawStr = "  paramount    13.11 nowe    soxxxxxx 23  diablo  13.11     .twisted sister   13.11 special 13.45 way";
const htmlStr = "  paramount    13.11 nowe    soxxxxxx 23  diablo  13<span class='mark' style='background: lime'>.</span>11     .twisted sister   13.11 special 13.45 way";
// 定位rawStr中第二个"13.11"的索引
const startIndex = rawStr.indexOf("13.11", rawStr.indexOf("13.11") + 1);
const endIndex = startIndex + 5; // "13.11"长度为5

const processedHtml = wrapTargetInHtml(rawStr, htmlStr, startIndex, endIndex);
console.log(processedHtml);

测试结果

运行上述代码后,输出的processedHtml与期望结果完全一致:

"  paramount    13.11 nowe    soxxxxxx 23  diablo  <span class='dsa' style='background-color:red'>13</span><span class='mark' style='background: lime'>.</span><span class='dsa' style='background-color:red'>11</span>     .twisted sister   13.11 special 13.45 way"

内容的提问来源于stack exchange,提问作者Travis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 17:03:33