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

正则匹配含间隔空格字符串并高亮:特殊语法正则失效求助

正则匹配高亮与字符串间隔空格兼容问题解决

问题背景

需要实现一个函数,接收任意正则表达式,在字符串中匹配所有结果并高亮。要求字符串每10个字符插入一个空格,但正则匹配时要忽略这些空格。当前使用<samp [innerHTML]="highlight(str, pattern)"></samp>(基于Bootstrap的samp标签设置字体),现有TypeScript代码仅支持纯字母/数字的正则(如LST、NSP),带特殊语法的正则(如L[ST]P、LS.+P、LS.{2,4}P)完全失效。

现有问题代码

public highlight(str: string, pattern: string) {
    let seqWithSpaces = this.insertSpaces(str, true);
    let patternWithSpaces = this.insertSpaces(pattern, false);
    
    return seqWithSpaces.replace(new RegExp(patternWithSpaces, "g"), match => {
            return '<span class="highlightText">' + match + '</span>';
        });
}
    
private insertSpaces(seq: string, isPatternSeq: boolean): string {
    let output: string = "";
        
    if (!isPatternSeq) {
        output = seq.replace(/(.{10})/g,"$1 ")
    } else {
        output = seq.replace(/(.{1})/g,"$1\s*")
    }

    return output;
}

解决方案

方案一:智能调整正则格式适配空格间隔

原代码的问题是给正则的每个字符都加了\s*,破坏了正则的特殊语法(比如字符组[ST]、量词+/{2,4})。正确做法是仅在正则的字面量字符之间插入\s*,保留特殊语法结构:

public highlight(str: string, pattern: string) {
    const spacedStr = this.insertSpaces(str, true);
    const processedPattern = this.processPatternForSpaces(pattern);
    
    return spacedStr.replace(new RegExp(processedPattern, "g"), match => {
        return `<span class="highlightText">${match}</span>`;
    });
}

private insertSpaces(seq: string, isTargetStr: boolean): string {
    if (isTargetStr) {
        // 目标字符串每10字符加空格,最后去除多余空格
        return seq.replace(/(.{10})/g, "$1 ").trim();
    }
    return seq;
}

private processPatternForSpaces(pattern: string): string {
    // 匹配正则中的特殊语法片段:字符组、转义字符、元字符、量词等
    const specialPartRegex = /(\[.*?\]|\\.|[\^$.*+?(){}|])/g;
    let processed = pattern.replace(specialPartRegex, (match) => {
        // 特殊片段直接保留,普通字面量字符前后加\s*
        return /(\[.*?\]|\\.|[\^$.*+?(){}|])/.test(match) ? match : `\\s*${match}\\s*`;
    });
    // 合并连续的\s*,避免冗余
    return processed.replace(/\\s\*\\s\*/g, "\\s*");
}

方案二:先匹配原字符串,再插入空格

彻底规避正则与空格的冲突:先在无空格的原始字符串上完成匹配和高亮标记,再插入间隔空格(跳过HTML标签):

public highlight(str: string, pattern: string) {
    const regex = new RegExp(pattern, "g");
    const matchPositions: { start: number, end: number }[] = [];
    let match;

    // 收集所有匹配的起始/结束位置
    while ((match = regex.exec(str)) !== null) {
        matchPositions.push({ start: match.index, end: match.index + match[0].length });
        // 处理正则包含g标志时的lastIndex问题,避免无限循环
        if (match[0].length === 0) regex.lastIndex++;
    }

    // 从后往前插入高亮标签,避免位置偏移
    let markedStr = str;
    for (let i = matchPositions.length - 1; i >= 0; i--) {
        const { start, end } = matchPositions[i];
        markedStr = `${markedStr.slice(0, start)}<span class="highlightText">${markedStr.slice(start, end)}</span>${markedStr.slice(end)}`;
    }

    // 插入每10字符的空格,跳过HTML标签内容
    return this.insertSpacesWithTags(markedStr);
}

private insertSpacesWithTags(str: string): string {
    let result = "";
    let charCount = 0;
    let inHtmlTag = false;

    for (const char of str) {
        if (char === '<') {
            inHtmlTag = true;
            result += char;
            continue;
        }
        if (char === '>') {
            inHtmlTag = false;
            result += char;
            continue;
        }

        if (inHtmlTag) {
            result += char;
            continue;
        }

        result += char;
        charCount++;
        // 每10个字符加空格,排除最后一个位置
        if (charCount % 10 === 0 && charCount !== str.length) {
            result += ' ';
        }
    }
    return result.trim();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 18:24:57