一、正则表达式
1、正则表达式概述
正则表达式( Regular Expression )是一种用于匹配字符串中字符组成的模式,用来检测某个字符串的组成是否符合某种要求或规则,通常用来验证表单:例如验证用户名只能由英文字母、数字、下划线组成。而且,正则表达式还可以用来替换页面中的一些敏感词,或者从字符串中获取我们想要的特定部分字符串。
在 JavaScript 中,正则表达式也是一种对象。目前在 JS 中我们主要是用正则表达式来进行表单验证,对用户输入的内容进行处理,以及对字符串进行处理等操作。
2、正则表达式的特点
① 灵活性、逻辑性和功能性很强。
② 可以用简单的表达式实现对字符串的复杂控制。
③ 表达式结构不太清晰,比较晦涩难懂。
④ 常用场景下的正则表达式可直接借鉴,参考网站:常用正则表达式
3、正则表达式的创建
在 JavaScript 中,创建正则表达式的方式有两种:构造函数方式 和 字面量方式。
① 调用 RegExp 对象的构造函数创建
// 案例代码 参数为字面量
var regexp = new RegExp(/123/);
// 或 参数为字符串
var regexp = new RegExp("123");
// 构造函数可以有两个参数 第一个参数表示正则规则 第二个参数表示匹配规则
// 第二个参数有三种值: g - 表示全局匹配 i - 表示忽略大小写 gi - 表示全局匹配并且忽略大小写。
var regexp = new RegExp(/123/, g);
// 或
var regexp = new RegExp("123", g);
② 利用字面量的方式创建 (常用)
// 案例代码
var rg = /123/; // 此时无论里面是字符串还是数字 都不需要加引号
// 可增加匹配规则参数
var rg = /123/g;
4、正则表达式的使用
① test()
调用正则对象的 test()
方法,用来检测字符串是否符合该正则表达式的规则,符合则返回 true 否则返回 false 。
// 案例代码
var rg = /123/;
console.log(rg.test(123));// 匹配字符中是否出现123 出现结果为true
console.log(rg.test('abc'));// 匹配字符中是否出现123 未出现结果为false
② exec()
调用正则对象的 exec()
方法,用来根据该正则表达式的规则对字符串进行搜索匹配,如果有匹配的字符串,则返回值为一个结果数组,否则返回值为null。结果数组中共存储了1个元素和3个字段:0(第一个元素)
- 匹配到的子字符串、groups
- 一个命名捕获组对象,如果没有定义命名捕获组,则为undefined、index
- 匹配到的字符位于原始字符串的基于 0 的索引值、input
- 匹配的原始字符串。
使用该方法匹配成功后,会在正则表达式对象上更新lastIndex
属性,值为当前匹配后所匹配的子字符串后的第一个字符在原字符串中的位置(从0开始),作用是指定下一次匹配的起始位置。
// 创建正则表达式
const regex1 = RegExp('foo*', 'g');
// 要进行搜索匹配的字符串
const str1 = 'table fooootball, foosball';
// 进行搜索匹配 并接收返回值
let array1 = regex1.exec(str1);
// 输出第一次搜索匹配的返回值
console.log('111---',array1);
// 输出结果数组的各项属性
console.log('0---',array1[0]);
console.log('groups---',array1.groups);
console.log('index---',array1.index);
console.log('input---',array1.input);
// 输出第一次搜索匹配后所匹配的子字符串后的第一个字符在原字符串中的位置
console.log(regex1.lastIndex);
// 进行第二次搜索匹配 从第一次搜索匹配后的lastIndex位置开始匹配
array1 = regex1.exec(str1);
// 输出第二次搜索匹配的返回值
console.log('222---',array1);
// 输出第二次搜索匹配后所匹配的子字符串后的第一个字符在原字符串中的位置
console.log(regex1.lastIndex);
// 进行第三次搜索匹配 从第二次搜索匹配后的lastIndex位置开始匹配
array1 = regex1.exec(str1);
// 输出第二次搜索匹配的返回值
console.log('333---',array1);
// 输出第三次搜索匹配后所匹配的子字符串后的第一个字符在原字符串中的位置
console.log(regex1.lastIndex);
输出结果:
③ String字符串的match()、matchAll()、replace()、search()、split()等方法
var str = 'andy和rad';
// match() - 获取第一个匹配到的子字符串的结果数组信息(与exec()相似),未匹配到返回null
var newStr = str.match(/d/);
console.log('match()---',newStr)
// 如果正则表达式加了 g 表示全局匹配 则match()只返回全局匹配到的子字符串组成的数组
var newStr = str.match(/d/g);
console.log('match() g ---',newStr)
// matchAll() - 获取字符串中所有匹配的子字符串的结果数组信息(迭代器iterator) 以二维数组的形式
// 只能通过数组解构 重新赋值数组的方式 来获取结果
var newStr = [...str.matchAll(/d/g)];
console.log('matchAll()---',newStr)
// replace() - 替换匹配到的字符串
var newStr = str.replace(/andy/, 'baby');
console.log('replace()---',newStr)
// search() - 获取字符串中第一个匹配的子字符串的起始index位置( 与test()相似 )
var newStr = str.search(/d/);
console.log('search()---',newStr)
输出结果:
5、正则表达式的组成
一个正则表达式可以由简单的字符构成,比如:/abc/ 、/123/ ,也可以由复杂和特殊的字符组成,比如 /ab*c/ 。其中的特殊字符又被称为元字符,例如: ^ 、$ 、+ 等,在正则表达式中都具有特殊的意义。
常见单字符:
\
:反斜杠表示转义字符,如果在一个普通字符前面加上\
,例如\b
,表示该字符是特殊字符,不能按照字面理解。如果在一个特殊字符前面加上\
,例如\*
,表示该字符不是特殊字符,应该按照字面理解。
|
:竖线表示或字符,在两个字符之间加上|
,例如:x|y
表示既可以匹配x
又可以匹配y
。
.
:小数点表示匹配除换行符(\n
或者字符串第一个字母前也有一个换行符)之外的任何其他字符,例如:.a
表示匹配字符a的前面不是换行符的情况
常见组合字符:
字符 | 说明 |
---|---|
\0 | 匹配 NULL(U+0000)字符 |
\n | 匹配换行符(U+000A) |
\r | 匹配回车符(U+000D) |
\f | 匹配换页符(U+000C) |
\t | 匹配水平制表符(U+0009) |
\v | 匹配垂直制表符(U+000B) |
\u**** | 匹配Unicode字符,例如\u2028(行终止符) |
更多特殊字符的含义可查询MDN:正则表达式
6、边界符
正则表达式中的边界符或者叫位置符,常用的主要有:
① ^
:匹配字符串开头的文本,表示开头必须符合某种规则。
② $
:匹配字符串结尾的文本,表示结尾必须符合某种规则,如果 ^
和 $
同时出现,则表示精确匹配,必须字符串全文符合某个规则。
③ \b
:匹配单词边界,加在前面,则表示这个词前面的第一个字符的位置,没有其他字符(空格不算),加在后面,则表示这个词后面第一个字符的位置,没有其他字符。但不支持中文字符。
④ \B
:与\b
正好相反,匹配非单词边界,加在前面,则表示这个词前面的第一个字符的位置,存在其他字符(空格不算),加在后面,则表示这个词后面第一个字符的位置,存在其他字符。但不支持中文字符。
⑤ 字符1(?=字符2)
:先行断言,表示匹配 字符1并且字符1后面紧跟着字符2 的情况,必须是紧跟着,中间不能有其他字符包括空格。
⑥ (?<=字符2)字符1
:后行断言,表示匹配 字符1并且紧跟在字符2的后面,必须是紧跟着,中间不能有其他字符包括空格。
⑦ 字符1(?!字符2)
:正向否定查找,表示匹配 字符1并且字符1后面没有紧跟着字符2 的情况。
⑧ (?<!字符2)字符1
:反向否定查找,表示匹配 字符1并且字符1前面没有紧跟着字符2 的情况。
// 正则表达式的匹配位置
var rg = /abc/; // 正则表达式里面不需要加引号 不管是数字型还是字符串型
// /abc/ 没加边界符 只要包含有abc这个字符串返回的都是true
console.log(rg.test('aabcd')); // true
// 加了 ^ 必须以 abc 开头
var reg = /^abc/;
console.log(reg.test('abcd')); // true
console.log(reg.test('aabcd')); // false
// 加了 $ 必须以 abc 结尾
var reg0 = /abc$/;
console.log(reg0.test('aabc')); // true
console.log(reg0.test('aabcd')); // false
// 同时加了 ^ 和 $ 则为精准精确匹配 要求必须是 abc字符串才符合规范
var reg1 = /^abc$/;
console.log(reg1.test('abc')); // true
console.log(reg1.test('aabcd')); // false
// 前面加了 \b 匹配单词前边界
// 含有abc字符串 并且a字符前边界位置不存在字符
var reg2 = /\babc/
console.log(reg2.test('aabc')); // false
console.log(reg2.test('abcc')); // true
console.log(reg2.test('123 abc 456')); // true
// 后面加了 \b 匹配单词后边界
// 含有abc字符串 并且c字符的后边界位置不存在字符
var reg3 = /abc\b/
console.log(reg3.test('aabc')); // true
console.log(reg3.test('abcc')); // false
console.log(reg3.test('123 abc 456')); // true
// 前后都加了 \b
// 含有abc字符串 且前后边界都不存在字符
var reg4 = /\babc\b/
console.log(reg4.test('aabc')); // false
console.log(reg4.test('abcc')); // false
console.log(reg4.test('123 abc 456')); // true
// 注意:中文不属于单词
var reg5 = /\b猪猪侠/
console.log(reg5.test('猪猪侠')); // false
console.log(reg5.test('猪猪侠的超级棒棒糖')); // false
console.log(reg5.test('勇敢的猪猪侠')); // false
// 前面加了 \B 匹配非单词前边界
// 含有abc字符串 并且a字符前边界位置存在字符
var reg6 = /\Babc/
console.log(reg6.test('aabc')); // true
console.log(reg6.test('abcc')); // false
console.log(reg6.test('123 abc 456')); // false
// 后面加了 \B 匹配单词后边界
// 含有abc字符串 并且c字符的后边界位置存在字符
var reg7 = /abc\B/
console.log(reg7.test('aabc')); // false
console.log(reg7.test('abcc')); // true
console.log(reg7.test('123 abc 456')); // false
// (?=) 先行断言
// 含有abc字符串 并且后面紧跟着123
var reg8 = /abc(?=123)/
console.log(reg8.test('abc123')); // true
console.log(reg8.test('abc 123')); // false
console.log(reg8.test('abc456')); // false
// (?!) 正向否定查找
// 含有abc字符串 并且后面没有紧跟着123
var reg8 = /abc(?!123)/
console.log(reg8.test('abc123')); // false
console.log(reg8.test('abc 123')); // true
console.log(reg8.test('abc456')); // true
// (?<=) 先行断言
// 含有abc字符串 并且紧跟在123后面
var reg9 = /(?<=123)abc/
console.log(reg9.test('123abc')); // true
console.log(reg9.test('123 abc')); // false
console.log(reg9.test('456abc')); // false
// (?<!) 反向否定查找
// 含有abc字符串 并且前面没有紧跟着123
var reg10 = /(?<!123)abc/
console.log(reg10.test('123abc')); // false
console.log(reg10.test('123 abc')); // true
console.log(reg10.test('456abc')); // true
7、字符类 [ ]
正则表达式的字符类 [ ] 表示有多种字符可供选择,只要匹配其中的一种,返回值就为 true 。
// 案例代码
var rg = /[abc]/; // 只要包含有a 或者 包含有b 或者包含有c 都返回为true
console.log(rg.test('andy'));//true
console.log(rg.test('baby'));//true
console.log(rg.test('color'));//true
console.log(rg.test('red'));//false
var rg1 = /^[abc]$/; // 加上边界符之后 三选一 只有是a 或者是 b 或者是c 这三个字母才返回 true
console.log(rg1.test('aa'));//false
console.log(rg1.test('a'));//true
console.log(rg1.test('b'));//true
console.log(rg1.test('c'));//true
console.log(rg1.test('abc'));// false
----------------------------------------------------------------------------------
var reg = /^[a-z]$/ //26个英文字母任何单独一个字母返回 true - 表示的是a 到z 的范围
console.log(reg.test('a'));//true
console.log(reg.test('z'));//true
console.log(reg.test('A'));//false
-----------------------------------------------------------------------------------
//字符组合
var reg1 = /^[a-zA-Z0-9]$/; // 26个英文字母(大写和小写都可以)任何单独一个字母或数字0-9的单独一个返回 true
------------------------------------------------------------------------------------
//取反 方括号内部加上 ^ 表示取反,只要包含方括号内的字符,都返回 false 。
var reg2 = /^[^a-zA-Z0-9]$/;
console.log(reg2.test('a'));//false
console.log(reg2.test('B'));//false
console.log(reg2.test(8));//false
console.log(reg2.test('!'));//true
8、量词符
正则表达式的量词符是用来设定字符出现的次数,通常与 [ ] 联合使用。
量词 | 说明 |
---|---|
* | 重复0次或更多次,等价于{0,}(贪婪) |
+ | 重复1次或更多次,等价于{1,}(贪婪) |
? | 重复0次或1次,等价于{0,1}(贪婪) |
{n} | 重复n次(贪婪) |
{n,} | 重复n次或更多次(贪婪) |
{n,m} | 重复n到m次 (贪婪) |
*? | 重复0次或更多次,等价于{0,}?(非贪婪) |
+? | 重复1次或更多次,等价于{1,}?(非贪婪) |
?? | 重复0次或1次,等价于{0,1}?(非贪婪) |
{n}? | 重复n次(非贪婪) |
{n,}? | 重复n次或更多次 (非贪婪) |
{n,m}? | 重复n到m次 (非贪婪) |
贪婪模式和非贪婪模式:
贪婪模式:能长则长,在符合匹配条件的前提下,尽可能匹配长的字符串。
非贪婪模式:能短则短,在符合匹配条件的前提下,尽可能匹配短的字符串。
// 案例代码
// 量词是设定某个模式出现的次数
var reg = /^[a-zA-Z0-9_-]{6,16}$/; // 这个模式只能输入英文字母 数字 下划线 中划线 并且长度在 6-16 之间
var str = 'aaaaaa'
// 贪婪模式
var reg0 = /a{1,}/
console.log(reg0.test(str)); // true
console.log(str.match(reg0)[0]); // aaaaaa
// 非贪婪模式
var reg1 = /a{1,}?/
console.log(reg1.test(str)); // true
console.log(str.match(reg1)[0]); // a
9、小括号 ()
正则表达式里的小括号表示优先级,可以将多个字符包裹起来,当做一个整字符串来进行校验。例如: /^ abc{2} $/ 只是让c重复2次 而不是abc重复2次。 /^ (abc){2} $/ 才是让abc重复2次
10、括号总结
① 大括号 量词符. 里面表示重复次数
② 中括号 字符集合。匹配方括号中的任意字符.
③ 小括号表示优先级
11、预定义类
预定义类是指某些常用的验证规则,被预先给定义好了,并用某些简单字符来代指它们。
// 案例代码 座机电话验证
var reg = /^\d{3}-\d{8}|\d{4}-\d{7}$/; // 在正则表达式中 或 用 | 来表示
12、正则替换 replace
replace() 方法用来实现字符串的替换操作,用来替换的参数可以是字符串也可以是正则表达式。当参数是正则表达式的时候,那这个正则表达式还可以有匹配规则参数: /表达式/参数 ,参数有三种值: g — 表示全局匹配 i – 表示忽略大小写 gi — 表示全局匹配并且忽略大小写。
// 案例代码
//普通替换 只替换第一个匹配到的字符
var str = 'abcabc'
var nStr = str.replace(/a/,'哈哈')
console.log(nStr) //哈哈bcabc
//全部替换g
var nStr = str.replace(/a/g,'哈哈')
console.log(nStr) //哈哈bc哈哈bc
//忽略大小写i
var str = 'aAbcAba';
var newStr = str.replace(/a/i,'哈哈')// "a哈哈bcAba"
//全局匹配并忽略大小写 gi
var str = 'aAbcAba';
var newStr = str.replace(/a/gi,'哈哈')// "哈哈哈哈bc哈哈b哈哈"
13、利用replace 过滤敏感词
// 案例代码
<textarea name="" id="message"></textarea> <button>提交</button>
<div></div>
<script>
var text = document.querySelector('textarea');
var btn = document.querySelector('button');
var div = document.querySelector('div');
btn.onclick = function() {
div.innerHTML = text.value.replace(/激情|gay/g, '**');
}
</script>