正则的创建
- 字面量创建方式
let reg = /^$/
- 实例创建 RegExp
- 构造函数创建方式,可以实现正则的拼接
- 传递的参数是一个字符串
- 利用字符串可以拼接的特点,能够实现正则传递变量
- 可以引入变量
- 如果出现转义字符,转义前面再加一个\
let reg = new RegExp('')
// */
// let m = 'moon';
// let reg1 = /^$/
// let reg = new RegExp('^'+m+'/d$')
// console.log(reg)
let str = '\\d';
let str1 = '\D'
console.log(str) // '\d'
console.log(str1) // 'D'
------------------------------------------------------------
var name="js"
var reg = new RegExp(name)///js/
var reg1 = new RegExp("\\d"+name)///\djs/
//如果出现转义字符,转义前面再加一个\
console.log(reg)
正则的基础
-
正则:属于引用数据类型
-
用来处理字符串的一个规则
-
正则由元字符和修饰符组成
-
test:检测,匹配:如果检测成功,返回true,没有检测成功返回false
-
exec:捕获;返回一个数组;其中第一项就是捕获到的内容,第二项捕获内容开始的索引,第三项是要检测的整个字符串的整体
-
match:
- 字符串的方法:匹配
- 他是字符串的一个方法,在String类的原型上,这个方法传递一个正则,
- 返回是是一个数组
- 如果正则不加g,跟exec返回值一样
- 加g;全局捕获;捕获多次,把符合正则内容的字符串都放到一个数组中;
- 缺点:如果要进行分组捕获,那他就拿不到分组捕获的内容了
-
注意:如果正则捕获不到内容返回值就是null
var str="ls199hh88";
var reg = /\d+/g;
//console.log(reg.test(str))
//console.dir(reg)
console.log(reg.exec(str))//["199", index: 7, input: "ls199hh88", groups: undefined]
console.log(reg.exec(str))//["88", index: 12, input: "ls199hh88", groups: undefined]
-------------------------------------------------------------------------------------
let reg = /^3$/
console.log(reg.test('3werr')) // false
console.log(reg.test('32'))
console.dir(RegExp)
console.log(reg.exec('3'))
// ["3", index: 0, input: "3", groups: undefined]
//
// 数组的第一项是捕获的内容
// index是捕获内容的开始位置的做引
// input是原字符串
正则的规则
-
正则由两部分组成:元字符和修饰符
-
修饰符:就是把正则额外的修饰一下
i: 不区分大小写
m:多行匹配
g:全局匹配 -
元字符:量词元字符、普通元字符、特殊元字符 (在正则中有特殊的含义的一些字符)
-
量词元字符:代表出现的次数
*:代表0到多次
+:出现一到多次
?:出现0到1次
{n}:出现n次
{n,}:至少出现n次
{n,m}出现n到m次 -
特殊元字符:单个或者多字符组合在一起具有特殊意义
\:转义字符:可以把普通元字符字符转换为特殊的元字符,也可以把特殊元字符转换为普通元字符 //
. :除了换行符以外的任意字符
^:以什么什么开头 //
$:以什么什么结尾 //
\n:换行符
\d:0-9之间的数字 //
\D:0-9以外的任意字符
\w:数字、字母、下划线 ,匹配包含下划线的任意字符[0-9a-zA-Z_]
\W:[^0-9a-zA-Z_]
\s:空白字符
\t是制表符,空格,为4个字符的空格
\b:单词边界
\B:匹配非单词边界
x|y:取x或y的任意一个 //
[xyz]:取x、y、z中的任意一个 //
[a-z]:在a到z范围内取一个 //
[^a-z]:取反,除了xyz中的任何一个
():分组 //
(?: ) :只匹配不捕获(没有空格)
(?=):正向预查
(?!):负向预查 -
普通元字符:
let reg = /name/
-
-
-
[\s\S] 意思是匹配所有 空白复字符+非空白字符 , 说白了也就是全部字符都可以
-
js去除字符串中的所有空格:
str.replace(/\s/g,"");
\s匹配单个空格字符,包括ASCII空格,制表符,换行符,回车符,垂直制表符和换页符
正则的分组 ()
1、改变了正则的优先级
// let reg = /^(18|29)$/ //18开头或者29结尾
// console.log(reg.test('18')) // true
// console.log(reg.test('29')) // true
// console.log(reg.test('189')) // true
// console.log(reg.test('129')) // true
// console.log(reg.test('28')) // false
2、分组引用
- 分组引用
- ([a-z])\1:相当于把前面一样的值拿过来,在出现一次
- \1:代指和第一个分组一模一样的内容
let str = 'moon'
let reg = /^[a-z]{4}$/
console.log(reg.test('asdf')) // true
let reg = /^[a-z]([a-z])\1\1[a-z]$/
console.log(reg.test('foood')) // true
3、分组捕获
- 正则捕获的时候会把最大的内容捕获一次,然后在把每一个分组捕获一次
- 用于小正则的捕获
- 小括号要进行捕获,从左往右依次进行捕获
let reg = /^([a-z])([a-z])\1\2$/
console.log(reg.test('qwqw')) // true
4.转义
- 转义字符( \可以把在正则中有特殊意义的字符转义为普通字符,也可以把普通字符转换以有意义的字符)
let reg = /^23\.45$/
.在正则中代除换行符外的任意字符
\可以把有特殊意义的元字符转换为普通字符,也可以把普通字符转换为有意义的元字符
console.log(reg.test('23e45')) // false
console.log(reg.test('23.45')) // true
// let reg = /^2.3$/ // 中间的点可以匹配换行符外的所有字符
// console.log(reg.test('2.3')) // true
// console.log(reg.test('2@3')) // true
// console.log(reg.test('2f3')) // true
// let reg = /^2\.3$/ // 我只想匹配数组2.3
// console.log(reg.test('2.3')) // true
// console.log(reg.test('2@3')) // fasle
// console.log(reg.test('2f3')) // false
- []
- 一般情况在中括号里出现的字符都是普通字符
- 中括号中不识别多位数
1、中括号里放的一般都是普通字符
let reg = /^[@+]$/
console.log(reg.test('+')) // true
console.log(reg.test('@')) // true
let reg = /^[\\d]$/
console.log(reg.test('d')) // true
console.log(reg.test('\\')) // true
2、中括号不允许出现多位数
let reg = /^[12-57]$/ // 1 2-5 7
console.log(reg.test('30')) // false
console.log(reg.test('1')) // true
console.log(reg.test('4')) // true
console.log(reg.test('7')) // true
console.log(reg.test('6')) // false
正则的正负向预查
- 正向预查 ?=
//ls后面必须跟haoren
var reg=/ls(?=haoren)/;
console.log(reg.test("lshaoren"))//true 这个正则能够匹配ls后面跟着haoren字符串
- 负向预查 ?!
- 如果ls后面跟着不是haoren的,能够匹配成功,返回true,否则返回false;
//ls后面必须跟不是haoren的
var reg=/ls(?!haoren)/;
console.log(reg.test("lshaoren"))//false
正则的捕获
- 小括号:也要进行以此捕获,从左往右依次进行捕获
- ?: 取消捕获(放在哪取消哪)
正则的懒惰性
- 在正则捕获时,如果第一次捕获到内容,就不会再继续捕获(这叫正则的懒惰性)
- 懒惰性:正则找到符合正则的值以后,就不再捕获了
- 取消正则的懒惰性,用正则的修饰符g
- g:每捕获一次,当前正则的lastIndex就会被修改成下一轮开始捕获的索引位置
- reg.lastIndex:是下一轮捕获开始的索引位置
数组的第一项是最大的捕获
以后数组的每一项是分组捕获的内容
index:第一次捕获的内容的开始位置的索引
input:原字符串
function myExec(str){
if(!this.global){
return this.exec(str)
};
let ary = [];
let res = this.exec(str)
while(res){
ary.push(res[0])
res = this.exec(str)
}
return ary.length === 0?null:ary;
};
RegExp.prototype.myExec = myExec;
console.log(reg.myExec(str))
正则的贪婪性
- 正则在匹配的时候能多匹配一个就多匹配一个,这就是正则的贪婪性
- 在量词元字符的右边出现?,那就是取消正则的贪婪性
- 贪婪性
- ?放在量词的后面是取消捕获的贪婪性的
// 正则的贪婪性
let str = 'ls2019ls2020';
let reg = /\d+?/g
console.log(str.match(reg)) //["2", "0", "1", "9", "2", "0", "2", "0"]
// 正则在匹配的时候能多匹配一个就多匹配一个,这就是正则的贪婪性
// 在量词元字符的右边出现?,那就是取消正则的贪婪性
exec的捕获
- exec:他是正则实例的一个公有属性,他是用来捕获符合规则的字符串的
- 1、返回值:是一个数组,如果捕获不到就是null
- 2、如果是数组
- 1、第一项是最大的捕获内容
- 2、以后数组的后几项就是分组捕获的内容
- 3、index是第一次捕获位置的索引
- 4、input是原字符串
- 3、如果你只匹配不捕获,就在小括号里加?:
- 4、exec只能捕获到第一次出现的符合正则规则的内容(这是正则捕获的懒惰型,默认只捕获第一个)
let reg1 = /^(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d)(\d|X)$/;
let str = '13073020020528421X';
console.log(reg1.exec(str))//["13073020020528421X", "130730", "2002", "05", "28", "1", "X", index: 0, input: "13073020020528421X", groups: undefined]
let reg = /\d{2}/g;
let str = 'w33w33ww';
console.dir(reg)
// 如果正则不加g,那每一次去捕获,捕获到的都是第一次符合规则的内容lastIndex的值不会变,都是0
// 如果正则加上g,那每捕获一次,正则的lastIndex就会记录当前捕获到的内容的最后一项索引,下次再捕获的时候从记录的索引的基础上+1,继续捕获
// console.log(reg.exec(str))
// console.log(reg.lastIndex)
// console.log(reg.exec(str))
// console.log(reg.lastIndex)
// console.log(reg.exec(str))
//match用exec捕获来模拟
// function myExec(str){
// // 如果正则不加g,那正则的私有属性global的值就是false,
// // 就给他捕获一次直接return就好了
// if(!this.global){
// return this.exec(str)
// };
// let ary = []; // 用来存放每一次捕获到的内容
// let res = this.exec(str) // 重新进行捕获
// while(res){
// // 每捕获一次就往ary里push一次捕获到的内容
// ary.push(res[0])
// // 然后在继续捕获
// res = this.exec(str)
// }
// // 如果正则第一次就捕获不到,while就不会执行,那ary是空数组,直接给他return null就好了
// return ary.length === 0?null:ary;
// };
// RegExp.prototype.myExec = myExec;
// console.log(reg.myExec(str)) // ['33', '33']
console.log(str.match(reg)) // ['33', '33']
通过match捕获
- match:
- 字符串的方法:匹配
- 他是字符串的一个方法,在String类的原型上,这个方法传递一个正则,
- 返回是是一个数组
- 如果正则不加g,跟exec返回值一样
- 加g;全局捕获;捕获多次,把符合正则内容的字符串都放到一个数组中;
- 缺点:如果要进行分组捕获,那他就拿不到分组捕获的内容了
- 自己封装的捕获方法
// 封装一个方法,当正则进行捕获的时候要拿到每一次全局捕获的内容,还要拿每一次分组捕获的内容
function execAll(str){
// 如果正则不加g,那正则实例身上的私有属性global就是false,反之就是true
if(!this.global){
// 直接给他捕获一次return 出去
return this.exec(str)
}
let big = [], // 创建一个大数组用来存储全局捕获的内容
small = [], // 创建一个小数组用来存储分组捕获的内容
res = this.exec(str) // 创建一个变量,用来存储每一次捕获的内容
while(res){
big.push(res[0])
small.push(res[1])
// 重复执行正则捕获这个动作
res = this.exec(str)
}
return big.length === 0?null: {big,small}
// 把捕获到的内容return出去
// console.log(res)
}
RegExp.prototype.execAll = execAll;
console.log(reg.execAll(str))
replace捕获
- replace :字符串的替换;原有字符串不发生改变,会得到一个替换之后的返回值;
- 每次只能替换一个
- 结合正则
- 用正则对字符串进行捕获,把捕获到的内容替换成后面的字符串
- 正则和回调函数
- 正则对字符串进行捕获,并且将回调函数的返回值覆盖捕获到的内容;
- 正则捕获几次,这个回调函数就执行几次
- 回调函数执行时,会把每一次捕获的内容当做实参传递给回调函数里
- 回调函数的返回值会把每一次捕获的内容替换
let str = 'ls33ls33'
// 我想把 'ls'替换为 'lshaoren'
// str = str.replace('ls', 'lshaoren').replace('ls', 'lshaoren')
// str = str.replace(/ls/g , 'lshaoren')
str = str.replace(/ls/g,function(){
console.log(arguments)
/*
1、正则匹配几次,这个回调函数就执行几次
2、回调函数的返回值会把每一次捕获的内容替换
3、回调函数执行时,会把每一次捕获的内容当做实参传递给回调函数里
*/
return 'lshaoren'
})
console.log(str)
---------------------------------------------------
var str = "123or456";
var newStr = str.replace(/\d+/g,function(a,b,c){
console.log(a);// 第一个参数是捕获到的内容
console.log(b);// 第二个参数捕获的内容开始的索引位置
console.log(c);// 原来的字符串
// console.log(100);
// return 1;
});
console.log(newStr);
例子:正则表达式
- 匹配有效数字:1、1.5、+2、0、-1
- 开头有可能是±号,也有可能没有 ?
- 如果是个位数[0-9] 两位数 ([1-9]\d+)
- 小数 (.\d+)? 可以不出现,也可以出现1次
// let reg = /^[+-]?(\d|([1-9]\d+))(\.\d+)?$/
// console.log(reg.test('2')) // true
// console.log(reg.test('2.5')) // true
// console.log(reg.test('-2')) // true
// console.log(reg.test('+2')) // true
// console.log(reg.test('2.')) // false
// console.log(reg.test('2..')) // false
// console.log(reg.test('3.1415926')) // true
- 匹配密码
- 6到16位组成
- 由数字、字母、下划线组成
// function fn(str){
// if(str.length<6 || str.length>16 ){
// alert('密码不符合规范');
// return
// }
// let ary = ['2','_','....'] // 由数字、字母、下划线组成
// for (var i = 0; i < str.length; i++) {
// if(!ary.includes(str[i])){
// alert('密码不符合规范');
// return
// }
// }
// }
- 邮箱
let reg = /^[a-zA-Z0-9-_]+@[a-z0-9]+(\.[a-z]+)+$/
//12344@qq.com
// let reg = /^[a-zA-Z0-9-_]+@[a-z0-9]+(\.[a-z]+)+$/;
// console.log(reg.test('12344@qq.com.cn')) // true
// console.log(reg.test('12344@qq.com')) // true
// console.log(reg.test('12344@qq..com')) // false
// console.log(reg.test('@qq.com')) // false
// console.log(reg.test('-@qq.com')) // false
- 匹配中文名字 [\u4E00-\u9FA5]
//let reg = /^[\u4E00-\u9FA5]{3,6}(·[\u4E00-\u9FA5]{2,6}){0,2}$/
// let reg = /^[\u4E00-\u9FA5]{2,6}(·[\u4E00-\u9FA5]{2,6}){0,2}$/;
// console.log(reg.test('爱新觉罗·溥仪'))
// console.log(reg.test('阿诺德·施瓦辛格'))
- 身份证
- 18位
- 前6位是省市
- 中间8位是生日
- 倒数四位
- 前两位是公安局代码
- 第三位是性别,奇数是男,偶数是女
- 最后一位是数字,有可能是X
//先确定最后一位
// let reg = /^\d{17}(\d|X)$/
//前六+中八
// let reg1 = /^(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d)(?:\d|X)$/;
// ?: 只匹配不捕获
//中八
// let reg2 = /^(\d{6})([1-2]\d{3})((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{2}(\d)(\d|X)$/;
// let reg3 = /^(\d{6})([1-2]\d{3})((0[1-9])|(1[0-2]))((0[1-9])|([1-2]\d)|(3[0-1]))\d{2}(\d)(\d|X)$/;
// // 年 1xxx - 2xxx
// // 月 01-09 10-12
// // 日 01-09 10-29 30-31
// let res = reg1.exec('13073020020528421X');
// console.log(res[2] + '年' + res[3] +'月' +res[4] +'日')
// // console.log(reg2.test('13073030020528421X'))
// console.log(reg1.exec('13073020020528421X'));
// console.log(reg1.exec('13073020020528421X222')); // null
// 正则捕获不到是null
// ["13073020020528421X", "130730", "2002", "05", "28", "1", "X", index: 0, input: "13073020020528421X", groups: undefined]
1、数组的第一次最大的捕获
2、以后数组的每一项是分组捕获的内容
3、index:第一次捕获的内容的开始位置的索引
4、input:原字符串
let str = '33ss33ss';
let reg = /\d{2}/g
console.log(reg.test(str))
console.log(reg.exec(str))
console.log(reg.lastIndex)
使用replace的例子
- 用函数把good good study day day up首字母变成大写
function toFirstUpperCase() {
let reg = /\b([a-z])[a-z]*\b/g;
// console.log(str.match(reg))
let newStr = this.replace(reg, function () {
// console.log(big, small)
// console.log(arguments)
let [word, firstWord] = arguments // 把每一次捕获的单词和分组捕获的单词首个字母解构出来
firstWord = firstWord.toUpperCase() // 把首字母转大写
word = word.slice(1) // 把单词从第二项开始截取
return `${firstWord}${word}` // 最后把转大写的开头字母和截取的字母组合到一起对捕获的内容进行替换
})
return newStr
}
String.prototype.toFirstUpperCase = toFirstUpperCase;
let str = 'good good study day day up';
console.log(str.toFirstUpperCase())
- 字符串时间格式化
- 在后台工作中会给我们返回字符串格式的时间
function formatTime(template = '{0}年{1}月{2}日 {3}时{4}分{5}秒'){
let timeAry = this.match(/\d+/g);// 把字符串里的年月日时分秒都拿到以数组的格式 ["2019", "12", "3", "12", "10", "3"]
// let template = '{0}年{1}月{2}日 {3}时{4}分{5}秒';// 编写一个模板,一会用来进行替换
template = template.replace(/\{(\d)\}/g, function(content, index){
// index是每一次分组捕获的内容
// console.log(content, index)
// console.log(timeAry[index])
let time = timeAry[index] || "00"; // 如果index获取不到对应的值,那就默认赋值为 "00"
time.length<2? time = "0"+time:null;
// 如果获取的时间不足十位就补零
return time
})
return template
console.log(timeAry)
}
String.prototype.formatTime = formatTime;
console.log(time.formatTime('{1}~{2} {3}:{4}'))
- 获取网址=号左右
let url = 'http://www.baidu.com?name=erYa&age=18#index';
function queryUrlParams() {
let reg = /([^?=&#]+)=([^?=&#]+)/g;
let obj = {}; // 创建一个空对象,用来存储一会处理的键值对
this.replace(reg, (content, key, value) => {
// content是每一次全局捕获的内容,
// key是每一次第一个分组捕获的内容(作为属性名)
// value是每一次第二个分组捕获的内容(作为属性值)
obj[key] = value;
});
// 把url里的参数捕获出来,以键值对的形式赋值给obj对象
this.replace(/#([^?=&#]+)/, (content, value) => {
// value是每一次分组捕获的内容(作为属性值)
obj['hash'] = value;
})
// 把url里的hash值捕获出来,以键值对的格式赋值给obj对象
return obj;
// 最后把obj对象return 出去
}
String.prototype.queryUrlParams = queryUrlParams;
console.log(url.queryUrlParams());
- 首字母小写转大写
var str = "my name is niu ,i am 28 years old";
var newStr = str.replace(/[a-z]+\b/g, function (a) {
return a[0].toUpperCase() + a.slice(1)
})
console.log(newStr);
- 把数字转成中文
var str = "20191214";
var ary = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖", "万", "仟"];
var newStr = str.replace(/\d/g, function (a) {
return ary[a]
})
console.log(newStr);
- 把下面时间格式化成2019年12月24日16时02分30秒
var str = "2019-12-24 16:02:30";
var ary = ["年", "月", "日", "时", "分", "秒"];
var newStr = "";
var i = 0;
str.replace(/\d+/g, function (a, b) {
newStr += a + ary[i++];
})
console.log(newStr);
- 加千分符,给下面的数字加’,'使其成为13,234,567,753,224
var str = "13234567753224";
//1
var newStr = str.replace(/^(\d{1,3})((\d{3})+)$/, function (a, b, c, ) {
console.log(arguments);//["13234567753224", "13", "234567753224", "224", 0, "13234567753224", callee: ƒ, Symbol(Symbol.iterator): ƒ]
var part2 = c.replace(/\d{3}/g, function (d,e) {
return ","+d
})
return b+part2
})
console.log(newStr);
//2
var str ="1234657753224";
var i=0;
var newStr=str.replace(/\d/g,function(a,b){
debugger;
if((str.length-b-1)%3===0&&str.length-1!=b){
return a+","
}else{
return a
}
})
console.log(newStr);
//3
str.toLocaleString('en-US');
结束语
- 感觉还可以的可以点赞、收藏加关注呦~
- 推荐三款正则可视化工具