正则表达式详解
一、正则的概念
1.概念:规则表达式,我们来书写一段规则,用于匹配一段字符串是否符合规则。
2.创建两种方式:
- 字面量的形式:const 变量 = /字符串内容/;
- 内置构造函数:const 变量 = new RegExp(字符串内容);
// 字面量的形式创建
let reg = /abc/;
// 以内置构造函数的形式创建
let reg1 = new RegExp('!@#abc');
// 答应结果:/abc/ /!@#abc/
console.log(reg , reg1);
二、正则的常用方法
1.有两种常用方法:
- 匹配:test
- 语法形式:正则表达式.test(字符串);
- 规范:如果符合就返回true,如果不符合规范就返回false。
- 捕获:exec
- 语法形式:正则表达式.exec(字符串);
- 规范:如果符合就返回数组,如果不符合规范就返回null。
// 定义一个正则表达式
let reg = /abc/;
let str = '111111111111';
let str1 = 'abcabc';
// 判断字符串形式是否符合正则表达式
// 第一种写法
console.log(reg.test(str)); // false
console.log(reg.test(str1)); // true
// 第二种写法
console.log(reg.test('abcabc')); // true
// 第三中写法
console.log(/abc/.test('1234')); // false
三、元字符
1.正则表达式的符号有哪些组成?
- 元字符:正则表达式的规则符号。
- 修饰符:修饰整个正则表达式符号。
2.元字符 - 普通元字符
- \d:
表示一位数字(0-9). - \D:
表示一位非数字(0-9). - \w:
表示数字(0-9)字母(a-zA-Z)下划线(_)其中一个. - \W:
表示除了数字(0-9)字母(a-zA-Z)下划线(_)这些字符的某一个字符. - \s:
表示一位空白字符. - \S:
表示一位非空白字符. - . :
表示一位非换行的任意字符. - \ :
表示转义符把有意义的符号转为有意义的文本,将没有意义的文本转为有意义的符号.
// \d 匹配字符串有一位数字
let reg = /\d/;
console.log(reg.test('123455')); // true
console.log(reg.test('1aqaqaq')); // true
console.log(reg.test('aaaaaa')); //false
// \D 匹配字符串有一位非数字
let reg1 = /\D/;
console.log(reg1.test('a123')); // true
console.log(reg1.test('acacac')); // true
console.log(reg1.test('1242535')); // false
// \w 匹配字符串内容是否有一位数字字母下划线符合正则表达式
let reg2 = /\w/;
console.log(reg2.test('abc')); // true
console.log(reg2.test('abc123')); // true
console.log(reg2.test('!@#')); // false
console.log(reg2.test('!@#123')); // true
console.log(reg2.test('abc!@#123')); // true
// \W 匹配字符串内容是否除了有一位数字字母下划线符合正则表达式
let reg2 = /\W/;
console.log(reg2.test('abc')); // false
console.log(reg2.test('abc123')); // false
console.log(reg2.test('!@#')); // true
console.log(reg2.test('!@#123')); // true
console.log(reg2.test('abc!@#123')); // true
// \s 匹配字符串内容是否有空白字符符合正则表达式
const reg = /\s/;
console.log(reg.test('a')); // false
console.log(reg.test('ab')); // false
console.log(reg.test('a b')); // true
console.log(reg.test(' ')); // true
// \S 匹配字符串没有空白字符符合正则表达式
let reg = /\S/;
console.log(reg.test(' ')); // false
console.log(reg.test('a')); // true
console.log(reg.test(' b')); // true
// . 匹配有非换行的任意字符符合正则表达式
let reg = /./;
console.log(reg.test('\n')); // false
console.log(reg.test('/n')); // true
console.log(reg.test('111\n')); // true
console.log(reg.test('\nqw')); // true
// \. 匹配有.的字符串内容出现
let reg = /\./;
console.log(reg.test('\.')); // true
console.log(reg.test('/n')); // false
console.log(reg.test('/.n')); // true
console.log(reg.test('111\n')); // false
console.log(reg.test('1.00')); // true
四、边界元字符
正则的边界元字符有两种:
1.^ 表示开头
2.$ 表示结尾
// 字符串内容有数字符合正则表达式
let reg1 = /\d/;
console.log(reg1.test('123abc')); // true
console.log(reg1.test('1')); // true
console.log(reg1.test('abc123')); // true
// 字符串开头符合正则表达式
let reg2 = /^\d/;
console.log(reg2.test('123abc')); // true
console.log(reg2.test('1')); // true
console.log(reg2.test('abc123')); // false
// 字符串结尾符合正则表达式
let reg3 = /\d$/;
console.log(reg3.test('123abc')); // false
console.log(reg3.test('1')); // true
console.log(reg3.test('abc123')); // true
// 字符串开头和结尾有一个是数字符合正则表达式
const reg4 = /^\d$/;
console.log(reg4.test('123abc')); // false
console.log(reg4.test('1')); // true
console.log(reg4.test('abc123')); // false
五、限定元字符
概念:表示前面一个符号出现了多少次。
1.*
- 表示0~正无穷次
2.+
- 表示1~正无穷次
- ?
- 表示0~1次
- {n}
- 表示限定n次 不能多也不能少
- {n,}
- 表示最少n次
- {n,m}
- 表示最少n次 最多m次
// * 表示0~正无穷大
let reg1 = /^\d*$/;
console.log(reg1.test('abc')); // false
console.log(reg1.test('123')); // true
// + 表示1~正无穷大
let reg1 = /^\d+$/;
console.log(reg1.test('abc')); // false
console.log(reg1.test('1abc')); // false
console.log(reg1.test('1abc1')); // false
console.log(reg1.test('111')); // true
// ? 表示0~1次
let reg1 = /^\d?$/;
console.log(reg1.test('1')); // true
console.log(reg1.test('a')); // false
console.log(reg1.test(' ')); // false
// {n} 表示只能出现n次
let reg1 = /^\d{3}$/;
console.log(reg1.test(123)); // true
console.log(reg1.test('abc')); // false
console.log(reg1.test('12')); // false
// {n,} 表示能出现n次到无穷大
let reg1 = /^\d{3,}$/;
console.log(reg1.test(123)); // true
console.log(reg1.test(123456)); // true
console.log(reg1.test(12344688)); // true
console.log(reg1.test('abc')); // false
console.log(reg1.test('12')); // false
// {n,m} 表示只能出现n次到m
let reg1 = /^\d{3,5}$/;
console.log(reg1.test(123)); // true
console.log(reg1.test(12345)); // true
console.log(reg1.test(12344688)); // false
console.log(reg1.test('abc')); // false
console.log(reg1.test('abc123')); // false
六、特殊元字符
正则的特殊元字符:
1.( )
- 含义1:当成一个整体;eg:(abc)把abc当成一个整体
- 含义2:到哪儿都捕获
2.|
- 含义:或
- eg:a|b 字符a或者字符b都行
3.[ ]
- 含义:包含
- 注意:[abcd]包含其中一位即可,[ ]实际代表的就是一位字符
4.[^]
- 含义:非
- 注意:[^abcd]只要不是他们四个中的一个即可,[^]实际代表的就是一位字符
5.-
- 含义:到(至)只能在这个范围中的一个
- 注意:通常包含[ ]和非^一起使用
- eg:[^0-9]表示不是0到9中的一个即可
// () 包含整体
let reg = /^(abc)$/;
let reg1 = /^(abc){3}$/;
console.log(reg.test('abc')); // true
console.log(reg.test('abcabc')); // false
console.log(reg.test('abcbc')); // false
console.log(reg1.test('abcabcabc')); // true
// | 或
let reg = /^(abc|def)$/;
let reg1 = /^(abc|def){2}$/;
console.log(reg.test('abc')); // true
console.log(reg.test('abcabc')); // false
console.log(reg.test('abcbc')); // false
console.log(reg1.test('abcabc')); // true
console.log(reg1.test('abcdef')); // true
console.log(reg1.test('defdef')); // true
// [] 包含其中一个
let reg1 = /^[abcdef]$/;
console.log(reg1.test('a')); // true
console.log(reg1.test('b')); // true
console.log(reg1.test('ab')); // false
console.log(reg1.test('!@#')); // false
// [^] 除了他们其中的任意一个字符
let reg1 = /^[^abcdef]$/;
console.log(reg1.test('a')); // false
console.log(reg1.test('b')); // false
console.log(reg1.test('ab')); // false
console.log(reg1.test('!')); // true
console.log(reg1.test('!@#')); // true
// - 包含其中一个
let reg1 = /^[a-f]$/;
console.log(reg1.test('a')); // true
console.log(reg1.test('b')); // true
console.log(reg1.test('ab')); // false
console.log(reg1.test('!')); // false
console.log(reg1.test('e')); // true
七、或的分界线区分
小练习
问题 :或(|)的分界线在哪里?答:或的分界线是小括号或者正则的边界(正则的尽头)
// abc开头 def结尾
let reg = /^abc|def$/;
console.log(reg.test('abc123def')); // true
console.log(reg.test('abc12345')); // true
console.log(reg.test('12345def')); // true
console.log(reg.test('12345')); // false
console.log('-------------------------------------');
// ab开头 ef结尾 cd中任选一个都行
let reg1 = /^ab(c|d)ef$/;
console.log(reg1.test('abcef')); // true
console.log(reg1.test('abdef')); // true
console.log(reg1.test('bdef')); // false
console.log(reg1.test('abde')); // false
console.log(reg1.test('acf')); // false
八、正则的重复元字符
符号:\1 \2 .... \9 。eg:/(abc)\1/ 在abc的后面重复一个abc 打印出abcabc
eg:/(abc|def)\1/
解释:小括号内为abc \1这个位置也需要是abc;小括号内为def \1这个位置也需要是def。
// \1重复字符
let reg = /^(123|abc)\1$/;
let reg1 = /^(123|abc){2}$/;
console.log(reg.test(123123)); // true
console.log(reg.test('123abc')); // false
console.log(reg.test('abcabc')); // true
console.log(reg1.test('123abc')); // true
// 标签判断
let reg = /^<(p|span)><\/\1>$/;
console.log(reg.test('<span></span>')); // true
console.log(reg.test('<p></p>')); // true
console.log(reg.test('<p></span>')); // false
console.log(reg.test('<span></p>')); // false
九、正则的标识符
正则的标识符
书写在正则的外边 用于描述整个正则表达式
-
i 忽略大小写 eg:/\w/i
-
g 全局判断 eg:/\w/g
// i 忽略大小写
let reg1 = /^[a-q]$/i;
console.log(reg1.test('A')); // true
console.log(reg1.test('BA')); // false
十、正则表达式的捕获
语法:正则.exec(字符串);
- 没有捕获到 直接返回一个null
- 如果捕获到 直接返回一个数组
-
2.1没有小括号也没有g的情况 永远捕获的都是开始下标0的第一个符合条件的内容
-
2.2没有小括号 但是有修饰符g的情况
- 第一次捕获完成后 第二次会从第一次捕获结束的位置开始
- 第一次开始的时候 会从第二次捕获结束的时候开始
- 当所有的匹配都匹配完成后 在捕获一次会返回一个null
- 当两次捕获的时候 就从下标0重新开始
-
2.3有小括号
- 下标0还是我们正常捕获到的内容
// 普通捕获
let reg = /\d{3}/;
console.log(reg.exec('abcabcabcdefdef')); // null
// 返回一个数组 捕获到下标为0的123
console.log(reg.exec('abcabc123abca456bc'));
// 重复捕获 返回和上面一样
console.log(reg.exec('abcabc123abca456bc'));
// g 全局捕获
let reg1 = /\d{3}/g;
console.log(reg1.exec('abcabcabcdefdef')); // null
console.log(reg1.exec('abcabc123abca456bc')); // 123
// console.log(reg1.exec('abcabc123abca456bc789')); // 456
// console.log(reg1.exec('abcabc123abca456bc789')); // 789
// console.log(reg1.exec('abcabc123abca456bc789')); // null
// console.log(reg1.exec('abcabc123abca456bc789')); // 123
// 有括号的时候
// 从18位身份证中获取18位数字
let reg2 = /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/;
let str = '我的身份证是522225200010031221';
console.log(reg2.exec(str));
十一、课堂案例
将正则捕获到的值放置在数组中。
let reg = /\d{3}/g;
let str = 'a123xc456vb789nm000';
const arr = [];
// 这里定义为const 是常量 值不可以改变
// let newArr = ;
while (reg.exec(str) !== null) {
arr.push(reg.exec(str)[0]);
// newArr = reg.exec(str);
}
console.log(arr);
/*
将正则捕获到的值,放置在数组中
代码处理后的arr === [123 , 456 , 789 , 000]
*/
十二、正则的两大特性
正则的两大特性
1.懒惰
- 正常捕获字符串的时候 每次都从下标0开始
- 解决方式:给正则添加一个修饰符g
2.贪婪
- 每次在捕获的时候 会尽可能的多捕获一些东西
- 解决:在原有的修饰符号后面添加一个?然后相当于开启非贪婪模式
-
贪婪能多拿就多拿
-
非贪婪能少拿就少拿
-
贪婪限定符:* + ? {n,} {n,m}
-
非贪婪限定符:*? +? ?? {n,}? {n,m}?
// 贪婪模式
// 把一整个都打印出来了
// 获取的结果是一个数组的形式 但是内容是下面
// 获取的结果是:<div><p>我是第一个p标签</p></div>
let str = '<div><p>我是第一个p标签</p></div>';
let reg = /<div.*>/;
console.log(reg.exec(str));
// 非贪婪模式
// 也就是在*号后面直接添加一个? 就可以将贪婪模式转化成非贪婪模式
// 获取的是一个数组的形式,其中的内容是:如下
// 获取的结果是:<div>
let str1 = '<div><p>我是第一个p标签</p></div>';
let reg1 = /<div.*?>/;
console.log(reg1.exec(str1));
十三、两种创建正则表达式的区别
let reg = /\w/ig;
console.log(reg);
let reg1 = new RegExp('\\w' , 'ig');
console.log(reg1);
/*
new RegExp('\w' , 'ig')
会把'\w' 把w转化为以一个具有特殊含义的字符 所以这一步没有什么意义
我们如果想要把正则表达式位\w \\w
*/
十四、字符串的方法
字符串的方法(search; match; replace);
从字符串中查找是否满足正则的条件:
1.search
- 语法形式:字符串.search(正则);
- 返回值:如果找到,返回首次出现满足条件的下标;如果没找到就返回-1
2.match
-
语法形式:字符串.match(正则);
-
返回值:返回一个数组 数组下标0是第一个捕获到的值 重复捕获都是下标0的那个位置的值;没有捕获到返回一个null
-
作用:当正则没有添加修饰符g的时候 作用类似于 正则.exec();如果添加了修饰符g,那么捕获到的以数组的形式返回满足条件的数值;没有捕获到的时候返回一个null
3.replace
- 语法形式:字符串.relpace(正则 , 要替换的字符);
- 作用:通过正则找到对应的字符 将其替换掉
// search方法
let reg = /\d{3}/;
let str1 = '你好在吗123在的456';
let str2 = '你好';
console.log(str1.search(reg)); // 返回4
console.log(str2.search(reg)); // 返回-1
// match方法
// 没有修饰符g的时候
let reg1 = /\d{3}/;
let str3 = '你好在吗123在的456';
let str4 = '你好';
console.log(str3.match(reg1)); // 返回一个数组 下标0的位置是满足条件的第一个数值
console.log(str3.match(reg1)); // 返回一个数组 还是从下标0的位置开始满足条件的第一个数值
console.log(str4.match(reg1)); // null
// 有修饰符g的时候
let reg2 = /\d{3}/g;
let str5 = '你好在吗123在的456';
let str6 = '你好';
console.log(str5.match(reg2)); // 返回一个数组 数组里面是满足条件的数值
console.log(str6.match(reg2)); // 返回一个null
// replace方法
let reg3 = /\d{3}/;
let reg4 = /\d{3}/g;
let str7 = '你好在吗123在的456';
let str8 = '你好';
console.log(str7.replace(reg3 , '*')); // 返回值:你好在吗*在的456
console.log(str7.replace(reg4 , '***')); // 返回值:你好在吗***在的***
console.log(str8.replace(reg4 , '*')); // 返回值:你好