正则(Regular Expression):是一个处理字符串的规则javascript
学习正则其实就是在学习如何编写规则,每个正则都是由元字符和修饰符两部分组成java
let reg = /^\d+$/g;
//字面量方式let reg2 = new RegExp(''||//, 'g');
//构造函数方式 第一个参数能够放变量经常使用的修饰符 | 全称 | 含义 |
---|---|---|
i | ignoreCase | 忽略大小写匹配 |
m | multiline | 多行匹配 |
g | global | 全局匹配 |
// m 修饰符 多行匹配
let str = ` 赵州桥 长江大桥 多孔桥 南浦大桥 `
let reg = /桥$/mg;
console.log(str.match(reg)); //["桥", "桥", "桥", "桥"]
复制代码
\d
0-9之间的一个数字\D
非0-9之间的任意字符\w
数字、字母、下划线中的的任意一个字符 /[0-9a-zA-Z_]/
\W
非数字、字母、下划线中的任意字符\s
匹配任意一个空白字符,包括:
// test() 方法用于检测一个字符串是否匹配某个模式.
let str = '1-7p';
let reg = /\b7p/;
console.log(reg.test(str)); //true
console.log(reg.exec(str)); //[7p...]
复制代码
\n
匹配一个换行符 (enter)let str = 'b7\np';
let reg = /^b7\np$/;
console.log(reg.test(str)); //true
console.log(reg.exec(str)); //["b7↵p"...]
console.log(str.match(reg)); //["b7↵p"...]
复制代码
\r
匹配一个回车符\
转义字符: 有两个做用
\d
;\.
此处的点不是任意字符,而是一个小数点.
不只是小数点,表明除了\n 之外的任意字符let reg = /^.$/;
console.log(reg.test('n')); //true
console.log(reg.test('1')); //true
console.log(reg.test('\n')); //false
console.log(reg.test('nn')); //false 只能是一位
复制代码
^
以某个元字符开头$
以某个元字符结尾x|y|z
x或者y中的任意一个(x和y是自定义的字母)[xyz]
x或者y或者z中的任意一个(xyz为自定义)[^xyz]
非x\y\z的任意字符[a-z]
获取a-z中的任意一个字符 [0-9] <=> \d[^a-z]
非a-z的任意字符()
正则分组(?:)
当前正则只匹配不捕获(?=)
正向预查(?!)
负向预查*
出现0到多个字符?
出现0到1个字符+
出现1到多个字符{n}
出现n个字符{n,}
出现n到多个字符{n,m}
出现n到m个字符// *能够出现0到屡次
let reg = /\d*/;
console.log(reg.test('')); //true
console.log(reg.test('52246')); //true
复制代码
//+ 能够出现1到屡次,可是不能一次都不出现
let reg = /\d+/;
console.log(reg.test('')); //false
console.log(reg.test('2')); //true
复制代码
// ?能够出现0-1次
let reg = /^\d?$/; //?能够出现0-1个字符
console.log(reg.test('')); //true
console.log(reg.test('5')); //true
console.log(reg.test('5262')); //false
复制代码
//{n}能够出现n个字符
let reg = /^\d{2}$/;
console.log(reg.test('')); //false
console.log(reg.test('2')); //false
console.log(reg.test('26')); //true
console.log(reg.test('2956')); //false
复制代码
//{n,}能够出现n到多个字符
let reg = /^\d{2,}$/;
console.log(reg.test('')); //false
console.log(reg.test('5')); //false
console.log(reg.test('861')); //true
复制代码
//{n,m}能够出现n次到m个字符
let reg = /^\d{2,4}$/;
console.log(reg.test('')); //false
console.log(reg.test('5')); //false
console.log(reg.test('52')); //true
console.log(reg.test('946')); //true
console.log(reg.test('9411')); //true
console.log(reg.test('55555')); //false
复制代码
只要在正则中出现的元字符(在基于字面量方式建立),除了特殊和有量词的之外,其他的都是普通元字符正则表达式
^$
和不加^$
的区别let reg = /\d+/; //=> 不加^和$,表明字符传中只要包含xxx便可
console.log(reg.test('kl55ijs56k')); //true 包含0-9之间的任意数字
复制代码
let reg1 = /^\d+$/; //=> 加^和$,表明字符传中必须以0-9中的任意数字为开头和结尾
console.log(reg1.test('kl55ijs56k')); //false
console.log(reg1.test('5222')); //true
复制代码
//方案一: 获取'a b',去掉先后空格
let str = ' a b ';
//第一个for循环去掉了a前面的空格
for (var i = 0; i < str.length; i++) {
if (str[i] !== ' ') {
//若是循环到字符串中各项不是空格,就强制中止整个循环
break;
}
}
str = str.substring(i);//此时 str用var i为全局变量
//第二个for循环去掉了b后面的空格
for (var k = str.length - 1; k > 0; k--) {
//从最后一位开始找,若是不是空格,就截取第一项到索引那项
if (str[k] !== ' ') {
str = str.substring(0, k + 1);
break;
}
}
console.log(str); //a b 去掉了先后空格
复制代码
//方案二: 获取'a b',去掉先后空格
let str = ' a b ';
str = str.trim(); //字符串方法:去掉字符串先后空格
console.log(str); //a b 去掉了先后空格
复制代码
//方案三: 获取'a b',去掉先后空格
let str = ' a b ';
let reg = /^\s+|\s+$/g; //以空格开头或者以空格结尾
console.log(str.replace(reg, ''));
复制代码
let reg = /^[.]+$/; //在这里只是小数点
console.log(reg.test('n')); //false
console.log(reg.test('1')); //false
console.log(reg.test('\n')); //false
console.log(reg.test('nn')); //false
console.log(reg.test('.')); //true
复制代码
但也有特殊状况,例如:数组
let reg = /^[\d]+$/; //在这里依然是表示0-9之间的任意数字
console.log(reg.test('2')); //true
console.log(reg.test('lks')); //false
复制代码
let reg = /^[18]$/; //只能是1或者8
console.log(reg.test('1')); //true
console.log(reg.test('8')); //true
console.log(reg.test('18')); //false
let reg1 = /[18]/; //包含1或者8就能够
console.log(reg1.test('1')); //true
console.log(reg1.test('8')); //true
console.log(reg1.test('18')); //true
console.log(reg1.test('958524')); //true
复制代码
let reg = /^[13-56]$/; // 不是13~56 而是1或者3~5或者6
console.log(reg.test('1')); //true
console.log(reg.test('8')); //true
console.log(reg.test('6')); //false
复制代码
// 一位数是正常的 从n到m
let reg = /^[2-5]$/;
console.log(reg.test('2')); //true
console.log(reg.test('8')); //false
console.log(reg.test('5')); //true
复制代码
=======浏览器
18-19 1[89] 20-59 [2-5]\d 60-65 6[0-5]函数
let reg = /^( ( 1[89] ) | ( [2-5]\d ) | ( 6[0-5] ) ) $/;
console.log(reg.test('19'));
//trueoop
let reg = /^[object .+]$/; console.log(reg.test('[object AAA]')); //true学习
let str = '这个case很是international';
let num = 0;
for (let item of str) {
//[\u4e00-\u9fa5] 中文区间 若是字符串中的各项为中文(即为true)
if (/[\u4e00-\u9fa5]/.test(item)) {
num += 2;
}else{
num += 1;
};
};
复制代码
//不加小括号的状况
let reg = /^12|14$/; // 12或者14或者以12开头或者以14结尾的均可以
console.log(reg.test('12')); //true
console.log(reg.test('14'));//true
console.log(reg.test('1214'));//true
console.log(reg.test('1258465414'));//true
console.log(reg.test('914'));//true
console.log(reg.test('123'));//true
console.log(reg.test('12ko'));//true
console.log(reg.test('+kj14'));//true
console.log(reg.test('12dsjjkn14'));//true
复制代码
let reg = /^(12|14)$/; // 分组改变默认优先级
console.log(reg.test('12')); //true
console.log(reg.test('14'));//true
console.log(reg.test('1214'));//false
console.log(reg.test('1258465414'));//false
console.log(reg.test('914'));//false
console.log(reg.test('123'));//false
console.log(reg.test('12ko'));//false
console.log(reg.test('+kj14'));//false
console.log(reg.test('12dsjjkn14'));//false
复制代码
let str = '2018---4//---/26//';
let reg = /(\d+)\D+(\d+)\D+(\d+)\D+/
let s = str.replace(reg,function($0,$1,$2,$3){
console.log($0); // 2018---4//---/26//
console.log($1); //2018
console.log($2); //4
console.log($3); //26
return `${$1}年${$2}月${$3}日`
});
console.log(s); //2018年4月26日
复制代码
关于replace的两个参数:请查看文末关于replace的内容ui
let reg = /^([a-z])([a-z])\2\1$/; //正则中出现的\1表明和第一个分组出现如出一辙的内容
console.log(reg.test('oppo')); //true
console.log(reg.test('poop')); //true
复制代码
let str = '437826357384623537463363726573384633278467382';
let min = -Infinity; //定义一个负无穷大的数
str = str.split('').sort().join('');
// 把乱序字符串用空字符串分割成数组,排序数组,再转成字符串,此时字符串为 '222223333333333333444445556666666777777788888'
/* \d 1个数字 \d\1 2个同样的数字 \d\1+ 2个到多个同样的数字 /(\d)\1+/g 没找到2个以上同样的数字,函数就执行一次 */
str.replace(/(\d)\1+/g, function ($0, $1) {
// console.log($0); //22222 3333333333333 44444 555 6666666 7777777 88888
// console.log($1); // 2 3 4 5 6 7 8
if (min < $0.length) {
min = $0.length;
let index = $1
};
})
console.log(min, index); // 13 "3"
复制代码
正则捕获使用字符串的match
方法(正则exec方法不经常使用)this
?:
,表明当前分组只匹配不捕获let str = '2019';
let reg = /(\d)+/;
console.log(str.match(reg));
// ["2019", "9", index: 0, input: "2019", groups: undefined]
// 不只把大正则的信息捕获到,子项的信息也捕获到
//注意:子项若是包了一个规则,在规则以后有量词,那么结果为最后一个
复制代码
+
-
号,能够没有,也能够有一个0
12
9
:一位或者多位数字,一位0-9
,多位数字不能以0
开头//利用正则检测有效数字
let reg = /^[+-]?(\d|[1-9]\d)(\.\d+)?$/
复制代码
let reg1 = /^1[3456789]\d{9}$/;
console.log(reg1.test('18704366271'));
复制代码
[\u4E00-\u9FA5]
[\u4E00-\u9FA5]{2,}
//中文姓名 1)中文汉字[\u4E00-\u9FA5]{2,} 2)
let reg = /^[\u4E00-\u9FA5]{2,}((·)([\u4E00-\u9FA5]{2,}))?$/;
console.log(reg.test('汤姆')); //true
console.log(reg.test('汤姆·')); //false
console.log(reg.exec('汤姆·')); // null
console.log(reg.test('汤姆·汉克斯')); //true
console.log(reg.exec('汤姆·汉克斯'));
复制代码
.
和 -
不能做为开头,不能连续出现 - 或者 .@
后面(域名):xxx.xx.xx
xxx.xx
xxx.xx.xx.xx
xxx-xxx-xx.xx.xx
let reg = /^\w+([-.]\w)*@[A-Za-z0-9]+([.-])[A-Za-z0-9]+)*(\.[A-Za-z0-9]+)$/
复制代码
let reg2 = /^\d{6}((18\d\d)|(19\d\d)|(20[01]\d))(0[1-9]|1[12])(0[1-9]|[12]\d|3[01])\d{3}[\dxX]$/;
console.log(reg2.test('220802199603241523'));
复制代码
test()
exec()
test()
match
split
replace
基于exec
能够实现正则捕获
null
0
:大正则捕获的内容index
:正则捕获的起始索引input
:原始操做的字符串exec
只能捕获到第一个和正则匹配的内容,其他匹配的内容尚未捕获到,并且执行屡次也无效 => 正则捕获的懒惰性正则捕获的懒惰性:只能捕获到第一个匹配的内容,剩余的默认捕获不到
let str = 'hello2018hello2019';
let str1 = 'hellohello';
let reg = /\d+/;
console.log(reg.test(str)); //true
console.log(reg.test(str1)); //false
console.log(reg.exec(str1)); // null
console.log(reg.exec(str)); //["2018", index: 5, input: "hello2018hello2019", groups: undefined]
复制代码
lastIndex
不变lastIndex
正则捕获时候,下一次在字符串中开始查找的索引let str = 'zhufeng2018zhufeng2019';
let reg = /\d+/;
console.log(reg.exec(str)); //=> 2018
console.log(reg.lastIndex); //=> 0
console.log(reg.exec(str)); //=> 2018
console.log(reg.lastIndex); //=>0
// 即便手动修改了lastIndex值 依旧无效
reg.lastIndex = 11;
console.log(reg.lastIndex); //=>0
复制代码
// 解决正则懒惰性:加全局修饰符g
let str = 'zhufeng2018zhufeng2019';
let reg = /\d+/g;
console.log(reg.lastIndex); //=> 0
console.log(reg.exec(str)); //=> 2018
console.log(reg.lastIndex); //=> 11
console.log(reg.exec(str)); //=> 2019
console.log(reg.lastIndex); //=>22
console.log(reg.exec(str)); //=> null
console.log(reg.lastIndex); //=>0
console.log(reg.exec(str)); //=> 2018
复制代码
let str = 'zhufeng2018zhufeng2019yangfan2020qihang2021';
let reg = /\d+/g;
RegExp.prototype.myExecAll = function(str){
// 为了防止出现死循环,咱们检测一下正则是否加g,没有加g只把第一次捕获的结果返回便可
if(!this.global){
return this.exec(str);
};
//this:reg 当前操做的正则
//执行exec开始捕获,具体捕获多少次不定,可是一直到捕获不到内容(null)为止,期间把捕获到的内容存储到数组中
let result = [];
let valAry = this.exec(str);
while(valAry){ //=>this.lastIndex < str.length
result.push(valAry[0]); //=>把每次捕获到的结果第一项(具体捕获的内容)存储到容器中
valAry = this.exec(str);
};
return result;
};
console.log(reg.myExecAll(str));
//["2018", "2019", "2020", "2021"]
复制代码
let str = 'zhufeng2018zhufeng2019yangfan2020qihang2021';
let reg = /\d+/g;
console.log(str.match(reg));
//["2018", "2019", "2020", "2021"]
复制代码
字符串方法:match
实现了本身编写的execAll处理的事情,但也要加全局修饰符g,把全部匹配的内容都捕获到,最后统一存储到一个数组中返回
match()
方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。
match
实现了本身编写的execAll
处理的事情,但也要加全局修饰符g
,把全部匹配的内容都捕获到,最后统一存储到一个数组中返回
let str = 'zhufeng{2018}zhufeng{2019yangfan{2020}qihang{2021}';
let reg = /\{(?:\d+)\}/g; //大括号有特殊含义:{n}出现的次数
console.log(reg.exec(str));
//["{2018}", "2018", ...]
console.log(str.match(reg)); //=>{2018}", "{2019}", "{2020}", "{2021}
复制代码
/\{(?:\d+)\}/g
=> ?:
是用来阻止分组捕获内容的 “只匹配不捕获”console.log(str.match(reg));
//=>{2018}", "{2019}", "{2020}", "{2021}
match方法也有本身的局限性,在正则设置了g
,基于match
捕获的内容只有大正则匹配的,小分组的内容没有单独抽取出来
每一次匹配捕获的时候,老是捕获到和正则匹配中最长的内容,例如:2
符合 \d+
2018
也符合 \d+
,可是捕获的是最长的内容 2018
let str = 'zhufeng2018zhufeng2019';
let reg = /\d+/g;
console.log(reg.exec(str)); //["2018", ...]
复制代码
解决方案:在量词元字符后面加?
, 表明的不是出现0-1次,而是取消正则捕获贪婪性
let str = 'zhufeng2018zhufeng2019';
let reg1 = /\d+?/g;
console.log(reg1.exec(str)); // ["2", ...]
复制代码
?
在正则中的做用/-?/
让减号出现或者不出现/\d+?/
只捕获最短匹配内容?:
只匹配不捕获?=
正向预查?!
负向预查test()
和exec()
test
进行匹配的时候,若是设置了g
,test
匹配也至关于捕获,修改了lastIndex
的值let str = 'zhufeng2018zhufeng2019';
let reg = /\d+/g;
console.log(reg.test(str)); //true
console.log(reg.lastIndex); //11
console.log(reg.exec(str));//["2019",...]
复制代码
let str = 'zhufeng2018';
let reg = /\d+/g;
console.log(reg.exec(str));//[2018] 把reg.lastIndex值修改了
console.log(reg.exec('zhufeng2018zhufeng2019')); //[2019] 虽然捕获的不是同一个字符串,可是正则是同一个,上一次正则处理的时候修改了它的lastIndex,也会对下一次匹配的字符串产生影响
复制代码
RegExp.$1
把上一次匹配(test/exec)到的结果获取到,获取的是第一个小分组匹配的内容,大正则匹配的内容没法获取,他是一个全局的值,浏览器中$1只有一个,其余的正则操做也会覆盖这个值,因此这种方式通常不用let str = 'zhufeng2018peixun2019';
let reg = /(\d+)/g;
console.log(reg.test(str)); //true
console.log(RegExp.$1); //2018
console.log(reg.test(str)); //true
console.log(RegExp.$1); //2019
console.log(reg.test(str));//false
console.log(RegExp.$1); //2019
console.log(reg.test(str));//true
console.log(RegExp.$1); //2018
复制代码
replace:实现正则捕获的方法(自己是字符串替换)
// 需求:把全部的'zhufeng'替换成'zhufengpeixun'
let str = 'zhufeng2018zhufeng2019';
let reg = /(\d+)/g;
str = str.replace('zhufeng','zhufengpeixun'); //一次只能替换一个,第二次仍是从索引[0]开始替换
复制代码
let str = 'zhufeng2018zhufeng2019';
str = str.replace(/zhufeng/g,'zhufengpeixun');
console.log(str); //zhufengpeixun2018zhufengpeixun2019
复制代码
//不经常使用
let str = 'zhufeng{val:2018}zhufeng{val:2019}';
reg = /\{val:(\d+)\}/g;
str = str.replace(reg,'#'); // 用reg正则和str字符进行匹配,匹配几回就替换几回,每一次都是当前“大正则”匹配的结果用第二个传递的字符串替换掉了
console.log(str); //zhufeng#zhufeng#
复制代码
//不常见
let str = 'zhufeng{val:2018}zhufeng{val:2019}';
reg = /\{val:(\d+)\}/g;
str = str.replace(reg,'$1'); // $1不是拿这个字符替换掉大正则匹配的内容,此处的$1表明第一个分组匹配的内容,等价于 RegExp.$1
console.log(str); //zhufeng2018zhufeng2019
复制代码
原理:string.replace(要替换的字符串||正则,替换成什么||函数);
//经常使用
let str = 'zhufeng{val:2018}zhufeng{val:2019}';
reg = /\{val:(\d+)\}/g;
str = str.replace(reg,(...arg) =>{
console.log(arg);
return 'AA';
});
console.log(str);//zhufengAAzhufengAA
复制代码
当第二个参数为函数的时候(默认状况下)
2.若是有小括号提权,则:
此函数必需要有return,否则默认为undefined
多个小括号嵌套的状况: /((\d+)\D+(\d+))\D+(\d+)\D+/
let str = '2018---4//---/26//';
let reg = /(\d+)\D+(\d+)\D+(\d+)\D+/
let s = str.replace(reg,function($0,$1,$2,$3){
console.log($0); // 2018---4//---/26//
console.log($1); //2018
console.log($2); //4
console.log($3); //26
return `${$1}年${$2}月${$3}日`
});
console.log(s); //2018年4月26日
复制代码
let str = '为人民服务,为人民奋斗,为人民努力'
let s = str.replace(/服务|奋斗|努力/g,function($0,$1){
let temp = '';
for (let i = 0; i < $0.length; i++) {
temp += '*';
};
console.log($0); //服务 奋斗 努力
return temp
})
console.log(s); // 为人民**,为人民**,为人民**
复制代码