在正则表达式中注入变量提取URL分段时结果异常,求解决方案
问题与解答
问题描述
现有URL:
let url = "https://gk.example.com/my-path/to/some+more/multiple.variables/moreparams";
需要提取其中的some+more和multiple.variables部分。最初分别编写了两个正则表达式实现需求:
- 匹配含
+的URL分段:/(?<=\/)([^\/]*\+[^\/]*)(?=\/)/g,通过url.match()调用后得到结果['some+more'] - 匹配含
.的URL分段:/(?<=\/)([^\/]*\.[^\/]*)(?=\/)/g,通过url.match()调用后得到结果['gk.example.com', 'multiple.variables']
为了避免用if分支切换正则,编写了一个注入分隔符变量的通用函数,但结果异常:
function getSplitUrl(sep, url) { if (!url) url = window.location.href; let regex = new RegExp('(?<=\/)([^\/]*'+sep+'[^\/]*)(?=\/)', `g`), results = []; results[0] = url.match(`(?<=\/)([^\/]*${sep}[^\/]*)(?=\/)`, `g`); results[1] = regex.exec(url); console.log('Regex 1: ', regex); // 输出的正则表达式看似正确,比如sep传入\.或\+时的格式符合预期 console.log(url, sep, results); return null; }
函数返回结果为['gk.example.com', 'gk.example.com'],后续发现url.match(regex)能得到正确结果,但regex.exec(url)却不行,想知道忽略了哪些关键点?
关键点解析
1. url.match()的参数错误
你调用url.match()时传入了模板字符串作为第一个参数,这是错误用法:match()的第一个参数必须是正则表达式对象,而非字符串。虽然JS会自动将字符串转为正则,但此时sep中的特殊字符(比如.、+)没有被转义,导致生成的正则不符合预期,错误匹配了gk.example.com。
正确写法应该直接使用提前创建好的regex对象:
results[0] = url.match(regex);
2. regex.exec()的全局匹配特性
当正则带有g(全局匹配)标志时,exec()的行为是每次调用从正则的lastIndex属性位置开始匹配:第一次调用返回第一个匹配项,第二次返回第二个,直到返回null表示匹配结束。你只调用了一次exec(),因此只会得到第一个匹配结果(也就是gk.example.com),而非所有符合条件的分段。
如果要通过exec()获取所有匹配结果,需要循环调用:
let match; const execResults = []; while ((match = regex.exec(url)) !== null) { execResults.push(match[0]); } results[1] = execResults;
3. 正则特殊字符的转义问题
.和+属于正则元字符(.匹配任意单个字符,+匹配前一个元素1次或多次),如果直接将它们作为sep传入正则,会导致匹配逻辑出错。需要先对sep进行转义:
function escapeRegExp(string) { return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); }
创建正则时使用转义后的分隔符:
let regex = new RegExp('(?<=\/)([^\/]*'+escapeRegExp(sep)+'[^\/]*)(?=\/)', `g`);
内容的提问来源于stack exchange,提问作者Evochrome
相关产品推荐
相关产品推荐

