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

JS正则表达式提取用户列表出现漏取异常,求原因及解决

问题描述

需要从字符串中提取带@前缀的用户列表,预期输入"Hello, @alice"时返回["alice"]。但使用以下代码处理字符串"Hello @user1 @user2 @user1@sdf.com @user2 @user1 @user1 @user2 "时,出现隔一个用户提取的问题,实际得到结果['user1', 'user1@sdf.com', 'user1', 'user2'],而非预期的['user1', 'user2', 'user1@sdf.com', 'user2', 'user1', 'user1', 'user2']。

原代码如下:

export const getRecepientsArrFromMessage = (value: string): string[] | [] => {
  if (value) {
    const REGEX = /(^@)([\wа-я]|@|.)/gi
    return value
      .trim()
      .split(' ')
      .filter((el) => el.length > 0 && REGEX.test(el))
      .map((el) => el.slice(1, el.length))
  }
  return []
}
问题原因
  1. 全局正则的test方法副作用:正则表达式添加了g全局标志后,RegExp.test()会维护一个lastIndex属性,记录上一次匹配结束的位置。每次调用test时,会从lastIndex的位置开始匹配,导致交替返回true和false,这就是用户被隔一个过滤掉的核心原因。
  2. 正则匹配逻辑冗余且不准确:原正则/(^@)([\wа-я]|@|.)/gi仅检查字符串是否以@开头且后面至少有一个字符,但没有确保整个元素都是合法的用户标识(比如能匹配@a!这类不符合预期的字符串),同时写法冗余([\wа-я]|@|.可简化为[\wа-я@.])。
解决方案

方案1:修复原代码的正则问题

去掉全局标志g,同时优化正则表达式,确保匹配完整的合法用户标识:

export const getRecepientsArrFromMessage = (value: string): string[] => {
  if (!value) return [];
  // 匹配以@开头,后面跟着字母、数字、下划线、俄文字母、@、点的非空序列
  const REGEX = /^@[\wа-я@.]+$/;
  return value
    .trim()
    .split(' ')
    .filter(el => el.length > 0 && REGEX.test(el))
    .map(el => el.slice(1));
}

方案2:使用matchAll一次性提取更高效

无需分割字符串,直接用正则全局匹配所有符合条件的用户标识,避免split可能带来的空格处理问题:

export const getRecepientsArrFromMessage = (value: string): string[] => {
  if (!value) return [];
  // 匹配所有以@开头,后面跟着合法字符的序列
  const regex = /@([\wа-я@.]+)/g;
  const matches = value.matchAll(regex);
  return Array.from(matches).map(match => match[1]);
}

效果验证

处理测试字符串"Hello @user1 @user2 @user1@sdf.com @user2 @user1 @user1 @user2 "时,两种方案都会返回预期结果:
['user1', 'user2', 'user1@sdf.com', 'user2', 'user1', 'user1', 'user2']

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 17:12:33