正则
什么是正则
regular expression 描述了一种字符串匹配的模式,可以检查一个串首付含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串
- 匹配 2. 捕获
正则匹配方法
- test exec 属于正则匹配捕获的方法
- match是字符串常用的方法,以及字符串常用的 replace 方法
编写正则表达式
1. 创建正则有2中方式
// 字面量的方式创建 (两个斜杠之间包裹起来的,都是用阿里描述规则的元字符)
let reg1 = /\d+/;
// 构造函数模式创建
let reg2 = new RegExp("\\d+");
// 如果使用引号则需要转译,适用的场景是如果需要变量拼接
// 如以下情况,中间的type为变量时
// new RegExp("^@"+type+"@$");
2. 正则表达式有2部分组成
- 元字符
- 修饰符 文件后缀匹配
// 以data开头中间由字母、数字、下划线、的任意字符, 以.data后缀结尾
data(\w)?\.dat
// data (\w)? \.dat
3. 常用元字符
| 符号 | 含义 |
|---|---|
| * | 0 或 1 或 多次 |
| + | >= 0 0或多次 |
| ? | 0 或 1次 |
| {n} | n次 |
| {n, } | n到多次 |
| { n, m } | n次到m次 |
4.常用元字符应用
- 在 * 号 与+ 号后面加 ? 去掉贪婪模式
// 匹配数字
var str = "123456";
var reg = /[0-9]{1,4}/;
// 匹配标签
var str = "<h1>点匹配的是任意字符</h1>";
var reg = /<.*?>/
//此处使用问号去掉贪婪模式
5.分组的副作用
- 会被缓存 ,使用 ?: 可以消除副作用
- ?= 、?<= 、 ?! 、?< ! 问等 、问小等 、问叹 、问小叹
// 匹配数字前面的runoob, 显然最后一个就不符合条件
var str = "123456runoob123runoob456runoobIAM"
var reg = /runoob(?=[\d+])/g;
str.match(reg); // ["runoob", "runoob"]
// 使用
var reg = (?![\d+])runoob;
6.特殊元字符
| 符号 | 含义 | ||
|---|---|---|---|
| \ | 转义字符(普通 转 特殊 转 普通) | ||
| . | 除\n(换行符)以外的任意字符 | ||
| 以哪一个元字符开始 | |||
| $ | 以哪一个元字符结束 | ||
| \n | 换行符 | ||
| \d | 0-9 之间的数字 | [0-9] | |
| \D | 非0-9之间的数字(大写与小写的意思是相反的) | ||
| \w | 数字、字母、下划线 [a-zA-Z0-9] | ||
| \W | 匹配非字母、数字、下划线。等价于[^a-zA-Z0-9_] | ||
| [0-9a-zA-Z_] | 匹配数字、字母、下划线与上面的相同 | ||
| \s | 一个空白字符 (包含空格、制表符、换页符) | ||
| \t | 一个制表符(一个TAB键:四个空格) | ||
| x | y | 或者y其中的一个字符1| 2| 9 | ||
| [xyz] | x或者y或者z其中的一个字符, 多个字符中的任意一个字符 | ||
| [^xy ] | 除了x/y以外的任意字符 | ||
| [a-z] | 执行a-z这个范围中的任意字符 | ||
| [^a-z] | 上一个取反的"非" , 在中括号中加^ 表示取非的意思 | ||
| () | 正则中的分组 | ||
| (?:) | 只匹配不捕获 | ||
| \b | 匹配单词边界,即字与空格间的位置 | ||
| \B | 非单词边界匹配 | ||
| (?=) | 正向预查 | ||
| (?!) | 负向预查 |
7.特殊元字符应用
以数字开头
var str = "123abc";
// + , 1或多个数字,abc结尾
var patt1 = /^[0-9]+abc$/;
var patt2 = /^\d+abc$/;
str.match(patt1);
// 使用exec捕获数字开头,会出现只捕获第一个,会出现懒惰模式
var str = '2021-08-25';
var reg = /^\d+/;
reg.exec(str);
// ["2021", index: 0, input: "2021-08-25", groups: undefined]
以特定的字符开头结尾^$
let reg = /^\d/; //以数字开始
/^\d/.test("jiajia"); // false
/^\d/.test('888jiajia'); // false
let reg2 = /\d$/; // 以数字结尾
let reg3 = /^\d$/;
/^$\d+/.test(2332); // 只能是数字
replace时间格式化
- 将2022-9-4转换成2022年9月4日
const time = "2022-9-4";
const reg = /^(\d{4})-(\d{1,2})-(\d{1,2})$/
time = time.replace(reg,(...args) => {
const [,$1,$2,$3] = args;
$2.length < 2 ? $2 = "0" + $2 : null;
$3.length < 2 ? $3 = "0" + $3 : null;
return $1 + "年" + $2 + "月" + $3 + "日";
})
- 时间戳
邮箱匹配
- 分组
const reg = /\w*((\.\w)|(\-\w))*@[a-zA-Z0-9]*((\.\w)|(\-\w))*\.[a-zA-Z0-9]*/
- 不同分组的等价实现
// 不同的分组实际效果是等价的
const reg1 = ((\.\w+)|(\-\w+))
const reg2 = ((\.|-)[A-Za-z0-9]+)
const reg3 = ((\.|-)\w+)
// reg1 等价于reg2 跟reg3
- ((.\w+)|(-\w+))
- ((.|-)\w+)
- ((.|-)[A-Za-z0-9]+)
- 邮箱的简易实现
const emailReg = /[\w.%+-]+@[\w.-]+\.[a-zA-Z]{2,4}/
转化成驼峰形式
var str = "get-element-by-id";
function toCalceCase(str){
var reg = /[-_]\w/g;
return str.replace((x) => {
return x.slice(1).toUpperCase()
})
}
单词边界\b
var str = "Chapter";
var reg = /ter\b/g;
// 则此时能匹配到
reg.exec(str); // ter
// 如果在单词的结尾加其他的单词则匹配不上
var str2 = "ChapterA";
reg.exec(str2); // 此时匹配不出任何结果
加千分位分隔符
var str = "1234567890";
var reg = /(?=(\d{3})+$)/
// ",123,456,789"
// 如何去掉第一个逗号呢? 使用负向预检,不匹配第一个 ?!^
reg = /(?!^)(?=(\d{3})+$)/g;
验证密码的合法性-(正向预检 ?=)
密码长度是6-12位,由数字、小写字母和大写字母组成,但必须至少包括2种字符
// 实现思路:
// 1. 密码长度是6-12位
// 2. 由数字、小写字符和大写字母组成
// 3. 必须至少包括2种字符
// 第一步写出条件1和条件2的正则
let regStep1 = /^[a-zA-Z\d]{6,12}$/
// 第二步 ,必须包含某种字符(数字、小写字母,大写字母)
let regStep2 = /?=.*\d/
// 第三步: 必须包含两种字符, 有四种排列组合方式
// 3.1 数字 + (大写字母 | 小写字母)
let reg1 = ((?=.*\d)|((?=.*[a-z])|(?=.*[A-Z]))
// 3.2 大写字母 | 小写字母
// 3.3 数字 + 大写字母 +小写字
- 3.1 数字 + (大写字母 | 小写字母)
((?=.*\d)|((?=.* [a-z])|(?=.*[A-Z])))
- 3.2 大写字母 + 小写字母
(?=.*[a-z])(?=.*[A-Z])
- 3.3 大写字母 + 数字 + 小写字母
(?=.*[A-Z])(?=.*\d)(?=.*[a-z])
- 最终综合
(?=.*[a-z])(?=.*[A-Z])|(?=.*[A-Z])(?=.*\d)(?=.*[a-z])|^[a-zA-Z\d]{6,12}$
手机号3-4-4分割扩展-(负向预检 ?<=)
- 123 => 123
- 1234 => 123-4
- 12345 => 123-45
- 123456 => 123-456
- 1234567 => 123-456
- 12345678 => 123-4567-8
- 123456789 => 123-4567-89
- 12345678911 => 123-4567-8911
- 第一步实现 123-4 如果使用正向预检,则 -1234,需要采用负向预检
const formatMobile = (mobile) => {
return String(mobile).slice(11)
.replace(/(?<=\d{3})\d+/, ($0) => '-' + $0)
}
- 实现123-1234-
const formatMobile = (mobile) => {
return String(mobile).slice(11)
.replace(/(?=\d{3})\d+/, ($0) => '-' + $0)
.replace(/(?<=[-\d]{8})\d{4}/, ($0) => '-' + $0)
}
查询字符串
- www.baidu.com
?a=1&b=2&c=4,获取查询字符后面的参数
// ?name=前端胖头鱼&" "&b=2&"
function queryParams(url,name){
// 以 [?&] ? 或则 & 字符开始
// name = 以&符开始的之间的 * 0-n个字符
let reg = new RegExp(`[?&]${name}=[^&]*(?:&|$)`)
let params = url.match(reg);
reutrn params? decodeURIComponent(params[1]:'');
}
8.正则表达式常用的修饰符
i ignoreCase 忽略大小写 m multiline 可以进行多行匹配 global 全局匹配
学习工具: