URL 正则表达式
在前端开发中,我们经常需要提取 URL 中的一些信息,例如域名、参数等等。这时候,我们就可以使用正则表达式来快速匹配 URL 中的各个部分。
URL 结构
一个标准的 URL 包含以下几个部分:
<scheme>://<user>:<password>@<host>:<port>/<path>?<query>#<fragment>
scheme
表示 URL 的协议,例如http
、https
、ftp
等等。user
和password
分别表示访问 URL 所需的账号和密码。host
表示主机名,可以是域名或者 IP 地址。port
表示端口号,默认为80
。path
表示 URL 请求的路径,可以包含多个层级的目录和文件名。query
表示 URL 的查询参数,可以传递多个键值对,使用&
分隔。fragment
表示 URL 的锚点,用于页面定位跳转。
提取 URL 中的信息
提取域名
使用正则表达式提取 URL 中的域名,例如把 https://www.baidu.com/index.html
地址中的 www.baidu.com
提取出来。正则表达式如下:
const url = 'https://www.baidu.com/index.html';
const pattern = /^[^/]+\/\/[^/]+/;
const domain = url.match(pattern)[0];
console.log(domain); // https://www.baidu.com
我们使用正则表达式 ^[^/]+\/\/[^/]+
,其中:
^
表示匹配行首。[^/]
表示匹配除了/
以外的任意字符。+
表示匹配前面的字符 1 次或多次。\/\/
表示匹配//
。[^/]+
同上。
注意,在提取出的域名后面应该加上 //
,否则后面的请求会出错。
提取 URL 参数
我们经常需要在 URL 中传递参数,这时候可以使用正则表达式来获取这些参数。例如,把 https://www.baidu.com/search?q=javascript&sort=vote&page=2
地址中的参数提取出来。正则表达式如下:
const url = 'https://www.baidu.com/search?q=javascript&sort=vote&page=2';
const pattern = /\?(\S*)/;
const paramsStr = url.match(pattern)[1];
console.log(paramsStr); // q=javascript&sort=vote&page=2
我们使用正则表达式 \?(\S*)
,其中:
\?
表示匹配?
。(\S*)
表示匹配非空白字符 0 次或多次,并用圆括号将结果捕获到分组中。
注意,取出分组中的参数字符串后,还需要进行进一步的处理,以便提取出每个键值对的具体信息。
提取 URL 中特定的参数值
在获取 URL 参数之后,有时候需要提取参数中特定键的值。例如,把 https://www.baidu.com/search?q=javascript&sort=vote&page=2
地址中的 q
参数提取出来。正则表达式如下:
const url = 'https://www.baidu.com/search?q=javascript&sort=vote&page=2';
const pattern = /q=([^&]*)/;
const value = url.match(pattern)[1];
console.log(value); // javascript
我们使用正则表达式 q=([^&]*)
,其中:
q=
表示匹配q=
。[^&]*
表示匹配非&
字符 0 次或多次,并用圆括号将结果捕获到分组中。
注意,在进行正则匹配时,应该首先判断 URL 是否包含该参数,如果存在则再截取参数的值。
const url = 'https://www.baidu.com/search?q=javascript&sort=vote&page=2';
const paramName = 'q';
const pattern = new RegExp(`${paramName}=([^&]*)`);
const match = url.match(pattern);
if (match) {
const value = match[1];
console.log(value); // javascript
}
我们使用 RegExp
构造函数动态生成正则表达式,其中:
${paramName}
表示插入变量paramName
的值。=
表示匹配=
。([^&]*)
同上。
注意,在使用动态正则表达式时,要谨慎处理转义字符,确保最终生成的正则表达式是正确的。
URL 防御式编程
由于 URL 是由用户输入的,存在恶意用户输入攻击 URL 的风险,因此我们还应该进行防御式编程,避免代码被注入攻击。
URL 校验
首先,我们需要对用户输入的 URL 进行校验,确保 URL 的合法性。可以使用正则表达式来验证 URL。
const url = 'https://www.baidu.com/index.html';
const pattern = /^(http|https|ftp):\/\/[\w\-]+(\.[\w\-]+)*([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?$/;
if (pattern.test(url)) {
console.log('URL is valid.');
} else {
console.log('URL is invalid.');
}
我们使用正则表达式 ^(http|https|ftp):\/\/[\w\-]+(\.[\w\-]+)*([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?$
,其中:
^
表示匹配行首。(http|https|ftp)
表示匹配http
、https
或ftp
。:\/\/
表示匹配://
。[\w\-]+
表示匹配字母、数字、下划线、连字符,至少匹配 1 次。(\.[\w\-]+)*
表示匹配.
后面跟字母、数字、下划线、连字符,至少匹配 0 次(即可以没有)。加上圆括号表示可以匹配多个这样的字符串。([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?
表示匹配 URL 路径和查询参数部分。$
表示匹配行尾。
注意,该正则表达式可以过滤掉一些字符,但并不能完全消除恶意攻击,因此需要进行进一步的防御。
URL 编码和解码
由于 URL 中可以包含一些特殊字符,而浏览器对这些字符的解释不一定相同,因此我们需要对 URL 进行编码和解码,以保证浏览器的解释结果一致。
// 编码
const url = 'https://www.baidu.com/search?q=javascript&sort=vote&page=2';
const encodedUrl = encodeURI(url);
console.log(encodedUrl); // https://www.baidu.com/search?q=javascript&sort=vote&page=2
// 解码
const decodedUrl = decodeURI(encodedUrl);
console.log(decodedUrl); // https://www.baidu.com/search?q=javascript&sort=vote&page=2
我们使用 encodeURI
和 decodeURI
方法对 URL 进行编码和解码,其中:
encodeURI
方法可编码 URL 中除字符A~Z a~z 0~9 - _ . ! ~ * ' ( ) ; : @ & = + $ , / ? # [ ]
以外的所有字符,编码后的字符使用%
加 ASCII 码的 16 进制表示,例如空格编码后为%20
。decodeURI
方法可解码encodeURI
编码的字符。
注意,在进行 URL 编码和解码时,应该谨慎处理字符串中包含的特殊字符,确保最终的编码和解码结果是正确的。
总结
本文介绍了如何使用正则表达式来提取和处理 URL 中的各个部分,以及如何进行防御式编程来避免恶意攻击。正则表达式是前端开发的基础技能之一,能够帮助我们快速解决很多问题,但也需要注意正则表达式的使用风险,并进行进一步的防御。