str.match()组合两个正则表达式无法得到预期合并匹配结果
正则组合空匹配与数字匹配时结果不符合预期的原因
现象复现
你观察到的三个测试场景的表现都是符合正则引擎运行逻辑的:
- 用
/|/g匹配字符串'0123456789'时,会得到11个空字符串匹配。空串可以命中字符串开头、每两个相邻字符的间隙、字符串结尾共11个位置,对应代码:const str = '0123456789'; const regexp = /|/g; const matches = str.match(regexp); console.log('Length = ' + matches.length); // 11 console.log(matches); // 11个空字符串组成的数组 - 用
/\d/g匹配同个字符串时,会命中全部10个数字字符,结果符合预期,对应代码:const str = '0123456789'; const regexp = /\d/g; const matches = str.match(regexp); console.log('Length = ' + matches.length); // 10 console.log(matches); // ['0','1','2','3','4','5','6','7','8','9'] - 用交替符合并两个规则,即
/|\d/g和/\d|/g,都无法得到预期的21个匹配结果,对应代码:const str = '0123456789'; const regexp1 = /|\d/g; const matches1 = str.match(regexp1); console.log('Length = ' + matches1.length); // 11 console.log(matches1); // 11个空字符串 const regexp2 = /\d|/g; const matches2 = str.match(regexp2); console.log('Length = ' + matches2.length); // 11 console.log(matches2); // ['0','1','2','3','4','5','6','7','8','9', '']
核心规则说明
结果和预期不符,本质是忽略了正则引擎的两个基础运行规则:
- 交替匹配(
|分支)遵循左优先原则:只要左侧分支在当前位置匹配成功,就直接返回结果,不会再尝试右侧分支的匹配。 - 全局匹配模式下,如果某一次匹配到的内容长度为0(即空串),引擎会触发空匹配防死循环机制,自动将下一次匹配的起始位置向后偏移1位,避免无限重复匹配同一个位置的空串。
匹配过程拆解
针对/|\d/g(空串分支在左侧)
由于空串分支写在最左侧,引擎在每一个位置都会优先匹配空串成功,根本不会触发右侧\d分支的匹配逻辑。整个匹配过程和单独写/|/g完全一致,最终只会得到11个空串结果。
针对/\d|/g(数字分支在左侧)
引擎会优先尝试匹配数字:
- 从位置0开始,依次匹配到0-9共10个数字,每次匹配长度为1,匹配完成后位置顺次后移1位
- 走完10个数字后,当前位置到了字符串末尾(索引10的位置),数字分支匹配失败,才会触发右侧空串分支,匹配到最后1个空串
最终结果就是10个数字加1个末尾空串,共11个匹配项。
为什么无法得到21个匹配结果
正则匹配的过程是线性单向推进的,同一个字符串位置只会产生一次匹配结果,不可能在同一个位置同时记录空串和数字两类匹配:
- 如果当前位置匹配到长度为1的数字,下一次匹配会直接从数字之后的位置开始,不会在数字前的间隙再额外匹配空串
- 如果当前位置匹配到空串,引擎会直接后移一位跳过下一个位置,不会再在同位置尝试其他分支的匹配
你预期的“11个空串+10个数字共21个结果”,本质是要求引擎在数字字符的位置同时匹配两个内容,这不符合正则的匹配逻辑。
内容的提问来源于stack exchange,提问作者EzioMercer
相关产品推荐
相关产品推荐

