如何修改JavaScript RegExp模式?基于已有正则对象创建新正则实例
优雅地基于现有RegExp对象生成新正则表达式
日常开发中,我们常会遇到需要基于一个已有的RegExp实例,扩展其匹配模式来创建新正则的场景,但直接处理很容易踩坑,咱们来一步步解决这个问题。
踩坑的错误写法(简洁但结果完全不对)
一开始可能会想当然地直接把正则对象转成字符串拼接,但RegExp.prototype.toString()的输出会包含首尾的斜杠,导致生成的正则完全不符合预期:
function addBarWrong(re) { return new RegExp(re+"bar"); } addBarWrong(new RegExp("foo")); // 输出: /\/foo\/bar/ —— 这显然不是我们想要的
初步可行但不够优雅的写法
为了得到正确结果,你可能会手动截取字符串去掉首尾斜杠,还要记得保留原正则的标志,但这种写法显得很繁琐:
function addBarUgly(re) { var reString = re.toString(); // 手动截掉首尾的斜杠 var pattern = reString.slice(1, reString.lastIndexOf('/')); // 手动拼接标志 var flags = (re.global ? 'g' : '') + (re.ignoreCase ? 'i' : '') + (re.multiline ? 'm' : ''); return new RegExp(pattern + "bar", flags); } addBarUgly(new RegExp("foo", "i")); // 输出: /foobar/i —— 结果正确,但写法太啰嗦
优雅的最终解决方案
其实RegExp对象本身就提供了专门的属性来获取模式和标志,根本不需要手动处理字符串:
function addBar(re) { // re.source 获取纯模式字符串(无首尾斜杠,内部转义已处理) // re.flags 获取所有标志(ES6+支持) return new RegExp(re.source + "bar", re.flags); } // 测试示例 addBar(new RegExp("foo", "gi")); // 输出: /foobar/gi addBar(new RegExp("foo\\/test")); // 输出: /foo\/testbar/ —— 转义字符也能正确保留
如果需要兼容ES6之前的旧环境,可以手动拼接标志:
function getRegFlags(re) { var flags = ''; if (re.global) flags += 'g'; if (re.ignoreCase) flags += 'i'; if (re.multiline) flags += 'm'; if (re.sticky) flags += 'y'; if (re.unicode) flags += 'u'; return flags; } function addBarLegacy(re) { return new RegExp(re.source + "bar", getRegFlags(re)); }
内容的提问来源于stack exchange,提问作者Bo Borgerson
相关产品推荐
相关产品推荐

