- 正则表达式创建的方式:
(1)字面量创建方式(两个斜杠之间包起来的,都是用来描述规则的元字符)
let reg1=/\d+/;
(2)构造函数模式创建 两个参数:元字符字符串
、修饰符字符串
let reg2=new RegExp("\d+"); - 正则表达式由两部分组成:元字符、修饰符。
(1)常用的元字符:
量词原字符——设置出现的次数,如下:
*-零到多次
±一次到多次
?-零次或者一次
{n}-出现n次
{n,}-出现n到多次
{n,m}-出现n到m次
特殊元字符:单个或者组合在一起代表特殊的含义,如下:
\——转义字符
.——除\n以外的任意字符
^——以哪一个原字符作为开始
$——以哪一个原子符作为结束
\n——换行符
\d——0~9之间的一个数字
\D——非0~9之间的一个数字
\w——数字、字母、下划线中的任意一个字符
\s——一个空白字符(包含空格、制表符、换页符等)
\t——一个制表符(一个TAB键:四个空格)
\b——匹配一个单词的边界
x|y——x或者y中的一个字符
[xyz]——x或者y或者z中的一个字符
[^xy]——除了x/y以外的任意字符
[a-z]——指定a-z这个范围中的任意字符
[^a-z]——取反
()——正则中的分组符号(?:)
——只匹配不捕获
(?=)——正向预查
(?!)——负向预查
普通元字符——代表本身含义的
/zhufeng/ ——此正则匹配的就是"zhufeng"
(2)修饰符——img
i——ignoreCase 忽略单词大小写匹配
m——multiline 可以进行多行匹配
g——global 全局匹配 - (1)
(2)
改变上面的情况,使用分组()
(3)中括号中出现的字符一般都代表本身的含义。
\d在中括号中还是0-9
中括号中不存在多位数
reg=/^[10-29]$/; //1或者0-2或者9
- 验证是否为有效数字
可能出现+ -号,也可能不出现:[±]?
一位0-9都可以,多位首位不能是0:(\d|([1-9]\d+))
小数部分可能有可能没有,一旦有后面必须是小数点加数字:(.\d+)? - 验证密码
let reg=/^\w{6,16}$/
- 验证真实姓名的
汉字:/^[\u4E00-\u9FA5]$/
名字长度2~10位
可能有译名 .汉字
let reg=/^[\u4E00-\u9FA5]{2,10}(.[\u4E00-\u9FA5]{2,10})?$/;
- 验证邮箱的
let reg=/^\w+((-\w+)|(\.\w+)*@[A-Z0-9a-z]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/;
\w+((-\w+)|(.\w+)*
开头是数字字母下划线(1到多位);
还可以是-数字字母下划线 或者 .数字字母下划线,整体零到多次;
邮箱的名字由“数字、字母、下划线、-、.”几部分组成,但是-/.不能连续出现也不能作为开始。
@[A-Z0-9a-z]+
@后面紧跟着:数字、字母(1-多位)
((.|-)[A-Za-z0-9]+)*
对@后面的名字的补充
多域名 .com.cn
企业邮箱 lly@tiantian-shangke-office.com
.[A-Za-z0-9]+
这个匹配最后的域名(.com/.cn/.org/.edu/.net…)
- 身份证
一共18位,最后一位可能是X:let reg=/^\d{17}(\d|X)$/;
身份证前六位省市县、中间8位 年月日、最后四位
小括号分组的第二个作用:分组捕获,不仅可以把大正则匹配的信息捕获到,还可以捕获到每个小分组的内容。
let reg=/^(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d)(\d|X)$/;
reg.exec("身份证号");
- 正则的捕获
(1)基于exec实现正则的捕获:捕获到的结果是null或者一个数组。
第一项:本次捕获到的内容;
其余项:对应小分组本次单独捕获的内容;
index:当前捕获内容在字符串中的起始索引;
input:原始字符串
每执行一次exec,只能捕获到一个符合正则规则的,但是默认情况下,我们执行一百遍,获取的结果永远是第一个匹配的,其余的捕获不到。
<script>
let str="xuexi2019jinbu2020fenyue2021";
let reg=/\d+/;
console.log(reg.exec(str));
</script>
正则捕获的懒惰性,懒惰性捕获的原因:
默认情况下lastIndex的值不会被修改,每一次都是从字符串开始位置查找,所以找到的永远只是第一个。解决:使用g
match方法
<script>
~function(){
function execAll(str){
//str:要匹配的字符串
//this:regexp的实例
if(!this.global) return this.exec(str);
let ary=[],
res=this.exec(str);
while(res){
//把每一次捕获的内容res[0]存放到数组中
ary.push(res[0]);
//只要捕获的内容不为NULL,则继续捕获下去
res=this.exec(str);
}
return ary.length===0?null:ary;
}
RegExp.prototype.execAll=execAll;
}();
let reg=/\d+/g;
console.log(reg.execAll(str));
//字符串中的MATCH方法,可以在执行一次的情况下,捕获到所有匹配的数据(前提正则也得设置G才可以)
console.log("lly2020".match(reg));
</script>
- 正则的分组捕获
<script>
let str="{0}年{1}月{2}日";
let reg=/\{(\d+)\}/g;
console.log(str.match(reg)); //多次匹配的情况下,match只能把大正则匹配的内容获取到,小分组匹配的信息无法获取。
let aryBig=[],
arySmall=[],
res=reg.exec(str);
while(res){
let [big,small]=res;
aryBig.push(big);
arySmall.push(small);
res=reg.exec(str);
}
console.log(aryBig,arySmall);
</script>
分组的第三个作用:“分组引用”——就是通过“\数字”让其代表和对应分组出现一模一样的内容
<script>
let str="book";
let reg=/^[a-zA-Z]([a-zA-Z])\1[A-Za-z]$/;
</script>
- 正则捕获的贪婪性
<script>
let str="lly2020@yy2021";
let reg=/\d+/g;
console.log(str.match(reg)); //["2020","2021"]
reg=/\d+?/g;
console.log(str.match(reg));//["2","0","2","0","2","0","2","1"]
</script>
- 问号在正则中的五大作用:
(1)问号左边是非量词元字符:本身代表量词元字符,出现0到1次。
(2)问号左边是量词元字符:取消捕获时候的贪婪性。
(3)(?:)只匹配不捕获
(4)(?=)正向预查
(5)(?!)负向预查 - test也能捕获
RegExp.$1~RegExp.$9:获取当前本次正则匹配后,第一个到第九个分组的信息。 - replace字符串中实现替换的方法(一般都是伴随着正则一起使用的)
<script>
let str="lly@2019|lly@2020";
str=str.replace('lly','李');
console.log(str); //只替换一次
</script>
<script>
let str="lly@2019|lly@2020";
str=str.replace(/lly/g,'李');
console.log(str); //全都替换
</script>
<script>
let time="2019-08-19";
//使其变为“2019年8月13日”
let reg=/^(\d{4})-(\d{1,2})-(\d{1,2})$/g;
// time=time.replace(reg,"$1年$2月$3日");
// console.log(time);
//还可以这样处理[str].replace([reg],[function])
//首先拿reg和time进行匹配捕获,能匹配到几次就会把传递的函数执行几次(而且是匹配一次就执行一次)
//不仅把方法执行,而且REPLACE还给方法传递了实参信息(和exec捕获内容一致的信息:大正则匹配的内容,小分组匹配的信息...)
//在函数中我们返回的啥,就把当前大正则匹配的内容替换成啥
time.replace(reg,(big,$1,$2,$3)=>{
console.log(big,$1,$2,$3);
}) //2019-08-19 2019 08 19
time=time.replace(reg,(...arg)=>{
let [,$1,$2,$3]=arg;
$2.length<2?$2='0'+$2:null;
$3.length<2?$3='0'+$2:null;
return $1+"年"+$2+"月"+$3+"日";
});
console.log(time); //2019年08月19日
</script>
单词首字母大写:
<script>
let str="good good study,day day up!";
let reg=/\b([a-zA-Z])[a-zA-Z]*\b/g;
str=str.replace(reg,(...arg)=>{
let [content,$1]=arg;
$1=$1.toUpperCase();
content=content.substring(1);
return $1+content;
});
console.log(str); //Good Good Study,Day Day Up!
</script>
16.正则表达式之获取最多出现的字母
验证一个字符中字母出现的次数最多,多少次?
(1)去重
<script>
let str="lilingyanchongchongchong";
let obj={};
[].forEach.call(str,char=>{
if(typeof obj[char] !== "undefined"){
obj[char]++;
return;
}
obj[char]=1;
});
console.log(obj);
let max=1;
let res=[];
for(let key in obj){
let item=obj[key];
item>max?max=item:null;
}
for(let key in obj){
let item=obj[key];
if(item===max){
res.push(key);
}
}
console.log(`出现次数最多的字符是:${res},出现了:${max}次`);
</script>
(2)排序
<script>
let str="lilinganchongchongcong";
str=str.split('').sort((a,b)=>a.localeCompare(b)).join('');
let reg=/([a-zA-Z])\1+/g;
let ary=str.match(reg); // ["ccc", "gggg", "hh", "ii", "ll", "nnnnn", "ooo"]
ary.sort((a,b)=>b.length-a.length);
//console.log(ary); //["nnnnn", "gggg", "ccc", "ooo", "hh", "ii", "ll"]
let max=ary[0].length;
let res=[ary[0].substr(0,1)];
for(let i=1;i<ary.length;i++){
let item=ary[i];
if(item.length<max){
break;
}
res.push(item.substr(0,1));
}
console.log(`出现次数最多的字符是:${res},出现了:${max}次`);
</script>
(3)
<script>
let str="lilingyanchongchongchong";
str=str.split('').sort((a,b)=>a.localeCompare(b)).join('');
// console.log(str); //"acccgggghhhiillnnnnnoooy"
let max=0,
res=[],
flag=false;
for(let i=str.length;i>0;i--){
let reg=new RegExp("([a-zA-Z])\\1{"+(i-1)+"}","g");
//i=3 content="hhh"或"uuu" $1=h或u(小分组中的内容即小括号中的内容)
let ary=str.replace(reg,(content,$1)=>{
res.push($1);
max=i;
flag=true
});
if(flag) break;
}
console.log(`出现次数最多的字符是:${res},出现了:${max}次`);
//出现次数最多的字符是:n,出现了:5次
</script>
17.时间字符串格式化
<script>
~function(){
function formatTime(template="{0}年{1}月{2}日 {3}时{4}分{5}秒"){
let timeAry=this.match(/\d+/g);
//(content,$1)可以写成(...[,$1])
return template.replace(/\{(\d+)\}/g,(content,$1)=>{
let tm=timeAry[$1]||"00";
return tm.length<2?tm="0"+tm:tm;
});
}
//扩展到内置类String.prototype上
["formatTime"].forEach(item=>{
String.prototype[item]=eval(item);
});
}();
let time="2020-9-16 10:59:2";
console.log(time.formatTime());
</script>
18.正则表达式之千分符
<script>
~function(){
function milliter(){
return this.replace(/\d{1,3}(?=(\d{3})+$)/g,content=>content+',');
}
["milliter"].forEach(item=>{
String.prototype[item]=eval(item);
})
}();
let num="123456789645";
console.log(num.milliter());
</script>