Appearance
JavaScript 正则表达式
导航目录
- 词量修饰符
- 匹配规则
- exec 方法
- match 方法
- 中括号中不存在多位数
- 手机号码验证
- 最多 2 位小数
- 中文姓名验证
- 身份证验证
- 正则贪婪模式
- 正则取消贪婪模式
- 计算出现最多的字母
- 首字母大写
- 日期格式化
- 获取 URL 参数
- 正则数组去重
- 实现 IndexOf 方法
- 匹配 hello 字符串后边要跟着 3 个数字
- 实现数组 each 函数
- 字母大小写转换
- URL 验证
- 同时满足字母大小写和数字
- 必须有下划线
- userName 转换为 user_name
- user_name 转换为 userName
词量修饰符
词量修饰符用于控制匹配字符出现的次数:
| 修饰符 | 说明 | 示例 |
|---|---|---|
| * | 零到多次 | a* 匹配零个或多个 a |
| + | 一到多次 | a+ 匹配一个或多个 a |
| ? | 零次或者一次 | a? 匹配零个或一个 a |
| {n} | 出现 n 次 | a{3} 匹配 3 个 a |
| {n,} | 出现 n 到多次 | a{2,} 匹配 2 个或更多 a |
| {n,m} | 出现 n 到 m 次 | a{2,4} 匹配 2 到 4 个 a |
匹配规则
正则表达式中的匹配规则说明:
| 符号 | 说明 | 示例 |
|---|---|---|
| **** | 转义字符 | \d 匹配数字 |
| . | 除换行符外的任意字符 | a.b 匹配 a 后跟任意字符再跟 b |
| ^ | 以哪一个字符作为开始 | ^a 匹配以 a 开头的字符串 |
| $ | 以哪一个字符作为结束 | a$ 匹配以 a 结尾的字符串 |
| \n | 换行符 | 匹配换行符 |
| \d | 0-9 数字 | \d+ 匹配一个或多个数字 |
| \D | 非 0-9 数字 | \D+ 匹配一个或多个非数字 |
| \w | 数字、字母、下划线 | \w+ 匹配一个或多个单词字符 |
| \s | 空白字符 | \s+ 匹配一个或多个空白字符 |
| \t | 一个制表符 | 匹配制表符 |
| \b | 匹配一个单词的边界 | \bword\b 匹配完整的单词 word |
| x|y | 匹配 x 或者 y | x|y 匹配 x 或 y |
| [zyc] | 匹配 x 或者 y 或者 c | [xyz] 匹配 x、y 或 z 中的任意一个 |
| [^ab] | 除了 ab | [^ab] 匹配除了 a 和 b 的任意字符 |
| () | 分组 | (ab) 将 ab 作为一个分组 |
| (?😃 | 只匹配不捕获 | (?:ab) 匹配 ab 但不捕获 |
| (?=) | 正向预查 | a(?=b) 匹配后面跟着 b 的 a |
| (?!) | 负向预查 | a(?!b) 匹配后面不跟着 b 的 a |
exec 方法
核心特性:全局模式下也只会匹配一次,需要手动设置 lastIndex
js
let reg = /(\d+)/g;
console.log(reg.exec("2020-12-11")); // 2020
reg.lastIndex = 4;
console.log(reg.exec("2020-12-11")); // 12
reg.lastIndex = 7;
console.log(reg.exec("2020-12-11")); // 11
console.log("2020-12-11".match(reg)); // ['2020', '12', '11']match 方法
核心特性:全部模式下会匹配所有
js
console.log("2020-12-11".match(reg)); // ['2020', '12', '11']中括号中不存在多位数
应用场景:验证中括号中不存在多位数,如 [189] 应该是 [1|8|9]
js
let reg = /^[189]$/;
console.log(reg.test(1)); // true
console.log(reg.test(8)); // true
console.log(reg.test(9)); // true
console.log(reg.test(189)); // false手机号码验证
应用场景:验证中国大陆手机号码格式
js
let reg = /^1[3456789]\d{9}$/;
console.log(reg.test(17624346544)); // true
console.log(reg.test(1762434654)); // false(位数不对)最多 2 位小数
应用场景:验证小数格式,最多 2 位小数
规则说明:
\d+只能是数字(\.\d{1,2})小数位后只能是一到 2 位数字?表示小数部分可选,0 到一次
js
let reg = /^\d+(\.\d{1,2})?$/;
console.log(reg.test(10)); // true
console.log(reg.test(10.2)); // true
console.log(reg.test(10.22)); // true
console.log(reg.test(10.222)); // false(超过2位小数)中文姓名验证
应用场景:验证中文姓名,2-4 个汉字
js
let reg = /^[\u4E00-\u9FA5]{2,4}$/;
console.log(reg.test("胡额")); // true
console.log(reg.test("张三")); // true
console.log(reg.test("李四")); // false(超过4个字)身份证验证
应用场景:验证中国大陆身份证号码格式
js
let reg = /^(\d{6})(\d{4})(\d{2})(\d{2})(\d{2})(\d)(\d|X|x)$/;
console.log(reg.exec("420881199411298114")); // 匹配成功正则贪婪模式
核心概念:尽可能找最大的匹配
js
let reg = /\d+/g;
console.log("2019@2020".match(reg)); // ['2019', '2020'](贪婪匹配)正则取消贪婪模式
核心概念:尽可能找最小的匹配
js
let reg = /\d+?/g;
console.log("2019@2020".match(reg)); // ['2', '0', '1', '9', '2', '0', '2', '0']计算出现最多的字母
算法说明:
\1匹配连续出现[a-zA-Z])\1:连续的相同字母- 字符先排序
- 遍历字符从索引结尾开始
- 正则匹配连续的字符
- 匹配到就终止循环
js
let str = "jabaambbjbcha";
str = str
.split("")
.sort((a, b) => a.localeCompare(b))
.join("");
let flog = false;
let max = 0;
let arr = [];
for (let index = str.length; index > 0; index--) {
if (flog) break;
var reg = new RegExp(`([a-zA-Z])\\1{${index - 1}}`, "g");
str.replace(reg, (content, $1) => {
max = content.length;
arr.push($1);
flog = true;
});
}
console.log(max, arr); // 输出:3 ['a', 'b']首字母大写
应用场景:将字符串中每个单词的首字母大写
js
let str = "after a while , charley lowered his head . he laughed and asked";
str = str.replace(/\b([a-zA-Z]+)\b/g, (content) => {
return content[0].toUpperCase() + content.substring(1);
});
console.log(str); // "After A While , Charley Lowered His Head . He Laughed And Asked"日期格式化
应用场景:将日期时间格式化为指定模板
js
function formatTime(template = "{0}年{1}月{2}日 {3}时{4}分{5}秒") {
let arr = this.match(/(\d+)/g);
return template.replace(/\{(\d+)\}/g, ([, $1]) => {
time = arr[$1] || "00";
return time.length === 1 ? "0" + time : time;
});
}
console.log(formatTime.call("2023-12-25", "{0}年{1}月{2}日 {3}时{4}分{5}秒"));
// "2023年12月25日 15时30分00秒"获取 URL 参数
应用场景:从 URL 字符串中提取参数
js
function queryUrlParams() {
let res = {};
this.replace(/([^?=&#]+)=([^?=&#]+)/g, (...[, k, v]) => (res[k] = v));
this.replace(/#([^?=&#]+)/g, (...[, v]) => (res["hash"] = v));
return res;
}
console.log(
queryUrlParams.call("https://example.com?name=John&age=25#section")
);
// { name: "John", age: "25", hash: "section" }正则数组去重
应用场景:使用正则表达式对数组进行去重
js
let arr = [1, 23, 43, 1, 45, 33, 45, 11, 33];
let str = arr.sort((a, b) => a - b).join("@") + "@";
arr = [];
str.replace(/(\d+@)\1*/g, (content, $1) => {
arr.push($1.replace("@", ""));
});
console.log(arr); // [1, 11, 23, 33, 43, 45]实现 IndexOf 方法
核心原理:match 匹配到会返回当前字符的位置,未找到返回 null
js
String.prototype.myIndexOf = function (str) {
let reg = new RegExp(str);
let res = this.match(reg);
return res === null ? -1 : res["index"];
};
console.log("aabbccb".indexOf("bbccb")); // 2
console.log("Blue Whale".indexOf("Blue")); // 0
console.log("Blue Whale".indexOf("Blute")); // -1
console.log("sfsdfsgssgdsgsdh".indexOf("h")); // 15
console.log("-----------------------");
console.log("aabbccb".myIndexOf("bbccb")); // 2
console.log("Blue Whale".myIndexOf("Blue")); // 0
console.log("Blue Whale".myIndexOf("Blute")); // -1
console.log("sfsdfsgssgdsgsdh".myIndexOf("h")); // 15匹配 hello 字符串后边要跟着 3 个数字
应用场景:验证特定格式的字符串
js
var reg = /\d{1,3}(?=\d{3})/g;
var str = "123456789";
str.replace(reg, (content, a, b) => {
console.log(content, a, b);
});
// 输出:123 456 789实现数组 each 函数
核心特性:
- 如何返回 false 终止循环
- 如果返回其他值,则改变原数组的值
js
Array.prototype.each = function (callback, self) {
if (Object.prototype.toString.call([]) !== "[object Array]")
return new Error("no is array");
const content = self || this;
for (let index = 0; index < this.length; index++) {
let result = callback.call(content, index, this[index]);
if (result === false) {
break;
}
if (result) {
this[index] = result;
}
}
};
let arr = [1, 2, 3, 4];
arr.each(function (index, item) {
console.log(index, item);
if (item === 2) {
return 20; // 修改数组值
}
});
console.log(arr); // [1, 20, 3, 4]字母大小写转换
应用场景:将字符串中的字母大小写互换
js
let str = "Abc";
let newStr = str.replace(/([a-zA-Z])/g, (content) => {
const tempStr = content.toLocaleUpperCase();
return tempStr === content ? content.toLocaleLowerCase() : tempStr;
});
console.log(newStr); // "aBC"URL 验证
应用场景:验证 URL 格式是否正确
规则说明:
(?:(http|https|ftp):\/\/)?:协议部分,0 次或者 1 次,只匹配不捕获((?:[\w]+\.)+[a-z0-9]+):域名部分,xx.xx((?:\/[^/?#]\*)+):路径部分(\?[^#]+):查询参数部分(#.+):锚点部分
js
let reg =
/^(?:(http|https|ftp):\/\/)?((?:[\w]+\.)+[a-z0-9]+)((?:\/[^/?#]*)+)?(\?[^#]+)?(#.+)?$/i;
console.log(reg.test("https://www.baidu.com/index.html?age=10#home")); // true
console.log(reg.test("baidu.com")); // false(缺少协议)
console.log(reg.test("https://www.baidu.com")); // true
console.log(reg.test("http://www.baidu.com.cn")); // true
console.log(reg.test("http://www.baidu.com.cn.net")); // true同时满足字母大小写和数字
应用场景:验证密码等需要同时包含大小写字母和数字的字符串
规则说明:
(?!^[a-zA-Z]+$):不能是全字母(?!^[0-9]+$):不能是全数字(?!^[a-z0-9]+$):不能是小写字母+数字(?!^[A-Z0-9]+$):不能是大写字母+数字^[a-zA-Z0-9]{3,}$:只能是数字字母,至少 3 位
js
let reg =
/(?!^[a-zA-Z]+$)(?!^[0-9]+$)(?!^[a-z0-9]+$)(?!^[A-Z0-9]+$)^[a-zA-Z0-9]{3,}$/;
console.log(reg.test("aaab")); // false(全字母)
console.log(reg.test("aaBva")); // false(小写字母+数字)
console.log(reg.test("11111144")); // false(全数字)
console.log(reg.test("adv44")); // false(小写字母+数字)
console.log(reg.test("AA44")); // false(大写字母+数字)
console.log(reg.test("aB4")); // true(符合要求)必须有下划线
应用场景:验证用户名等必须包含下划线的字符串
规则说明:
(?!^[a-z0-9A-Z]+$):不能是纯字母数字^\w{6,10}$:6-10 位字母数字下划线(?=_)\w+:必须以下划线开头
js
let reg = /(?!^[a-z0-9A-Z]+$)^\w{6,10}$/;
console.log(reg.test("ssssdfd_")); // true
console.log(reg.test("_ssssfd_")); // true
console.log(reg.test("_sssfd_s11")); // true
let reg2 = /(?=_)\w+/;
console.log(reg2.test("_ssssdfd_")); // true
console.log(reg2.test("_ssssfd_")); // true
console.log(reg2.test("_sssfd_s11")); // trueuserName 转换为 user_name
应用场景:将驼峰命名转换为下划线命名
js
let userName = "userName";
userName = userName.replace(/([A-Z])/g, (a) => `_${a.toLocaleLowerCase()}`);
console.log(userName); // "user_name"user_name 转换为 userName
应用场景:将下划线命名转换为驼峰命名
js
let user_name = "user_name";
user_name = user_name.replace(/_(\w)/g, ([, $2]) => `${$2.toUpperCase()}`);
console.log(user_name); // "userName"