本文已参与「新人创作礼」活动,一起开启掘金创作之路。
前言
本文记叙了通过正则表达式,快速将URL中的参数提取出来,转换为JSON的方法。
测试数据
从某个网站复制过来的地址,用作本文的测试数据:
// 未格式化
const url = 'https://xxxxx.com/mall/active/index.html?unionActId=31142&d=JtkkCmX&s=&cu=true&utm_source=so.lenovo.com.cn&utm_medium=tuiguang&utm_campaign=t_330412191_&utm_term=1b803c150d2348a09035010e4d1a2c07'
// 格式化
const url = `https://xxxxx.com/mall/active/index.html
?unionActId=31142
&d=JtkkCmX
&s=
&cu=true
&utm_source=so.lenovo.com.cn
&utm_medium=tuiguang
&utm_campaign=t_330412191_
&utm_term=1b803c150d2348a09035010e4d1a2c07`
废话不多说,既然是借助正则表达式的,那么先把对应的正则表达式写出来。
正则表达式
- 通过上面格式化之后的地址,可以清楚的看到,
URL中所有的参数都在?和&这两个符号之后,那么直接用反向肯定预查就行,先把参数位置匹配的表达式写出来:
const reg = /(?<=[\? | \&])/g
- 找好位置之后,就是匹配参数了,参数可以分为三个部分: 键、
=、值。如unionActId=31142,那么unionActId就是键,31142就是值,因为需要解析成JSON,所以键与值不能在一个子表达式中匹配,要分开匹配,方便后续的操作。
- 键的可以是数字、英文、中文、特殊符号等,但是键中一定不存在
=,结合步骤1,不难看出,键是处于?或&之后的连续的非=的字符组成的字符串,所以其正则表达式可以写成:
const reg = /(?<=[\? | \&])([^=]+)/g
- 然后再匹配键与值之间的
=:
const reg = /(?<=[\? | \&])([^=]+)=/g
- 然后就是值,也是同样可以拥有很多的字符类型,但是也同样有例外,值不能包含
&字符,这个字符是URL中用来连接各个参数用,一旦出现,视为上一个参数结束了,开始下一个参数,所以匹配起来也很简单,直接匹配连续且不为&的字符组成的字符串,正则表达式为:
const reg = /(?<=[\? | \&])([^=]+)=([^\&]+)/g
可以看到,已经将所有参数匹配起来,除了
&s=这个字符串,因为其没有值,所以匹配不到;如果需要将其也匹配进来,那么将匹配值的+换成*即可,不再赘述。
提取处理
有了正则表达式之后,通过String的replace函数,便能将所有参数匹配出来。replace函数的第二个参数可以是一个函数callback,callback会接到多个传参,在本文,使用callback前三个参数就足够,不妨将三个参数命名为$1、$2、$3; 先执行以下代码,打印出结果再解释为什么前三个参数就足够:
// 匹配参数的正则表达式
const reg = /(?<=[\? | \&])([^=]+)=([^\&]+)/g
// 测试用的地址
const url = 'https://xxxxx.com/mall/active/index.html?unionActId=31142&d=JtkkCmX&s=&cu=true&utm_source=so.lenovo.com.cn&utm_medium=tuiguang&utm_campaign=t_330412191_&utm_term=1b803c150d2348a09035010e4d1a2c07'
// replace函数的回调函数
const replaceCallBack = ($1, $2, $3) => {
console.log('$1:', $1)
console.log('$2:', $2)
console.log('$3:', $3)
console.log('============================>')
}
url.replace(reg, replaceCallBack)
打印结果:
可以看出来,$1是整个正则表达式匹配的结果,$2是键,$3是值。
$2是正则表达式中第一个捕获字符串的子表达式的结果,在本文的正则表达式中,第一个子表达式是(?<=[\? | \&]),但它只匹配位置,不捕获字符串,所以$2就是第二个子表达式([^=]+),因为这个子表达式是整个正则表达式中第一个捕获字符串的子表达式。
以此类推,$3就是第二个捕获字符串的子表达式,也就是匹配值的子表达式([^\&]+)。
接着,就是将replace函数的回调函数replaceCallBack改造一下,将所有的键与值整理成JSON即可,完整代码如下:
// 匹配参数的正则表达式
const reg = /(?<=[\? | \&])([^=]+)=([^\&]+)/g
// 测试用的地址
const url = 'https://xxxxx.com/mall/active/index.html?unionActId=31142&d=JtkkCmX&s=&cu=true&utm_source=so.lenovo.com.cn&utm_medium=tuiguang&utm_campaign=t_330412191_&utm_term=1b803c150d2348a09035010e4d1a2c07'
// 记录参数的JSON
const params = {}
// replace函数的回调函数
const replaceCallBack = ($1, $2, $3) => {
params[$2] = $3
}
// 执行正则表达式匹配
url.replace(reg, replaceCallBack)
// 打印参数
console.log('params:', params)
执行结果:
注意:因为需要匹配整个
URL中所有的参数,所以正则表达式必须加上全局匹配的g,或者使用replaceAll函数。