JavaScript正则表达式的行为
我在一个HTML文档中有以下JavaScript代码。
var a = "abc=def&ghi=jkl&mno=pqr".split(/(^|&).*?(=|$)/);
console.log("0='" + a[0] + "' 1='" + a[1] + "' 2='" + a[2] + "' 3='" + a[3] + "' 4='" + a[4] + "' 5='" + a[5] + "' 6='" + a[6] + "' 7='" + a[7] + "' 8='" + a[8] + "' 9='" + a[9] + "' a='" + a + "'")
预期输出如下。
0=`def` 1=`jkl` 2=`pqr` 3=`undefined` 4=`undefined` 5=`undefined` 6=`undefined` 7=`undefined` 8=`undefined` 9=`undefined` a=`def,jkl,pqr`
但实际得到的是如下所示。
0=`` 1=`` 2=`=` 3=`def` 4=`&` 5=`=` 6=`jkl` 7=`&` 8=`=` 9=`pqr` a=`,,=,def,&,=,jkl,&,=,pqr`
- 为什么
=和&子字符串没有被作为分隔符的一部分进行匹配,从而进入数组? - 为什么数组开头会有两个空子串?
- 如何获得预期的输出?
解决方案
- 为什么
=和&子字符串没有被匹配为分隔符的一部分,因此进入数组?
它们位于捕获组中,因此会包含在结果数组中。 Reference
如果
separator是一个正则表达式,返回的Array也包含每个分隔符匹配的 captured groups;详见下文。
- 为什么在数组开头会有两个空子串?
Example 同上,第一次要匹配的分隔符是 '^abc=', 左边是空字符串,第一次捕获是 '^',所以是空字符串,第二个捕获是 '=', 然后该分割的右半部分是 'def'。
- 如何获得预期的输出?
- 在不修改正则表达式的前提下,只需跳过那些已知的索引。
"abc=def&ghi=jkl&mno=pqr".split(/(^|&).*?(=|$)/).filter((x,i) => i && i%3===0)
2.将正则的捕获组设为非捕获组,并跳过在 '^' 之前的匹配。
"abc=def&ghi=jkl&mno=pqr".split(/(?:^|&).*?(?:=|$)/).slice(1)
3.如果你确实能够实现你已经假设的一切,请以多步方式进行分割
"abc=def&ghi=jkl&mno=pqr".split('&').map(x => x.split('=')[1])
4.与其尝试分割,不如直接使用带前瞻/后顾断言的正则匹配(regexr.com提示某些浏览器不支持,但在主流浏览器中似乎工作正常)
"abc=def&ghi=jkl&mno=pqr".match(/(?<==).*?(?=&|$)/g)
5.使用 URLSearchParams
不确定这是否与你真正想要做的事情相关,但它是处理查询字符串的内置工具。
var params = new URLSearchParams("abc=def&ghi=jkl&mno=pqr");
Array.from(params.keys()).join(','); // 'abc,ghi,mno'
Array.from(params.values()).join(','); // 'def,jkl,pqr'