正则表达式在线测试可用,TypeScript中失效问题排查
问题回顾
你用正则/([^\-\/\*\+]+)/g来拆分数学公式输入(比如(income - outgoing) * years working),在线正则测试工具跑出来都是预期的["(income ", " outgoing)", " years working"],但在TypeScript里用pattern.exec(str)执行时,结果却变成了["(income ", "(income "],换成str.match(pattern)就正常了——这事儿我之前也碰到过,其实是exec()方法的特性搞的鬼。
为啥会出问题?
带g标志的正则表达式实例会维护一个叫lastIndex的内部指针,每次调用exec(),都会从这个指针的位置开始往后匹配。如果你的代码里重复调用了同一个正则实例的exec(),或者循环的时候没处理好这个指针,就会导致匹配位置跑偏,出现重复或者遗漏的结果。
而str.match(pattern)就简单多了,它会一次性扫描整个字符串,返回所有匹配的结果,完全不依赖正则实例的lastIndex状态,所以结果是对的。
怎么解决?
方法1:直接用String.match()(亲测有效)
这是最省心的办法,直接调用字符串的match方法,一步到位拿到所有匹配项:
const formula = "(income - outgoing) * years working"; const splitPattern = /([^\-\/\*\+]+)/g; const matchedResult = formula.match(splitPattern); console.log(matchedResult); // 输出 ["(income ", " outgoing)", " years working"]
方法2:非要用exec()?记得重置lastIndex
如果因为业务需求必须用exec(),那每次匹配前一定要把正则实例的lastIndex重置为0,清除之前的匹配状态:
const formula = "(income - outgoing) * years working"; const splitPattern = /([^\-\/\*\+]+)/g; const result = []; let currentMatch; // 关键:重置lastIndex,避免之前的匹配状态干扰 splitPattern.lastIndex = 0; while ((currentMatch = splitPattern.exec(formula)) !== null) { result.push(currentMatch[1]); } console.log(result); // 同样得到正确结果 ["(income ", " outgoing)", " years working"]
额外提一句
你的正则逻辑本身是没问题的,就是匹配所有不包含-、/、*、+的连续字符序列。在线测试工具每次都是从头开始匹配,不会保留lastIndex,所以结果正常;但本地代码里如果复用了同一个正则实例,就容易踩这个坑。
内容的提问来源于stack exchange,提问作者David Perry

