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

如何修改TypeScript正则表达式避免连续匹配丢失目标子串?

解决正则分割连续目标子串丢失匹配的问题

问题背景

我们需要实现字符串分割功能:将输入字符串按照指定集合wordsToBold中的子串分割为数组,要求匹配到的子串作为独立元素存在。例如:

  • 当wordsToBold = ["test"],输入字符串"hi this is a test string",分割结果应为["hi this is a ", "test", " string"]。

此前修改正则后已支持非空格分隔的子串匹配,但遇到子串连续出现的场景时会丢失匹配:

  • 当wordsToBold = ["foo", "bar"],输入字符串"Thisfoo is a foobar sentence bar",当前分割结果为["This", "foo", " is a ", "foo", " sentence ", "bar"],其中foobar中的bar未被匹配到。

问题原因

默认正则匹配是非重叠匹配:当匹配到foo后,正则指针会移动到foo的末尾位置,导致后续的bar被跳过,无法被检测到。

解决方案

通过零宽度断言或包含目标子串/普通文本的全局匹配实现,确保匹配不占用字符位置,或覆盖所有可能的匹配场景。

方案1:全局匹配法(推荐)

构建正则同时匹配"目标子串"或"非目标子串的连续字符",通过全局匹配直接得到分割后的数组:

// 转义正则特殊字符
escapeRegExp(text: string): string {
  return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

splitStringByTargetWords(input: string, wordsToBold: string[]): string[] {
  if (!wordsToBold.length) return [input];

  // 转义所有目标子串,拼接为交替匹配模式
  const escapedWords = wordsToBold.map(this.escapeRegExp);
  // 正则规则:匹配目标子串,或匹配任意字符直到下一个目标子串(非贪婪模式)
  const matchRegex = new RegExp(`(${escapedWords.join('|')})|(?:(?!${escapedWords.join('|')}).)+`, 'g');

  // 执行匹配并过滤空元素
  return input.match(matchRegex)?.filter(part => part.length > 0) || [];
}

测试验证:
输入"Thisfoo is a foobar sentence bar",分割结果为["This", "foo", " is a ", "foo", "bar", " sentence ", "bar"],foobar被正确拆分为"foo"和"bar"两个元素。

方案2:零宽度分割法

利用正向/反向预查实现零宽度分割,分割时不消耗目标子串,从而支持连续匹配:

escapeRegExp(text: string): string {
  return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

splitStringByTargetWords(input: string, wordsToBold: string[]): string[] {
  if (!wordsToBold.length) return [input];

  const escapedWords = wordsToBold.map(this.escapeRegExp);
  // 零宽度分割:在目标子串的前后位置分割
  const splitRegex = new RegExp(`(?<=(${escapedWords.join('|')}))|(?=(${escapedWords.join('|')}))`, 'g');

  // 分割后过滤空值和undefined
  return input.split(splitRegex).filter(part => part && part.length > 0);
}

关键要点

  1. 正则转义:必须转义目标子串中的特殊字符(如.、*),避免干扰正则语法解析。
  2. 零宽度断言:(?=...)(正向预查)和(?<=...)(反向预查)不占用字符位置,确保连续子串都能被匹配。
  3. 全局匹配/分割:添加g修饰符,确保遍历整个字符串处理所有匹配场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 21:42:46