一、REGEXP对象
JavaScript通过内置对象RegExp支持正则表达式 有两种方法实例化RegExp对象:
- 字面量:
var reg = /\bis\b/g;
- 构造函数
var reg = new RegExp ('\\bis\\b','g');
//两个\是因为在字符串中\需要转义
修饰符:
g
:全文搜索,不添加,搜索到第一个匹配为止
i:
忽略大小写,默认大小写敏感
m
:多行搜索
对于有换行符/n的正则表达式,在document.write();中会被识别为分隔符即空格,因此要看出换行效果,只能console.log。 正常情况下键盘的回车等于 /r/n,/r等于一行的结束, /t代表制表符Tab。
二、正则表达式组成
1.元字符
- 原意文本字符:代表它本来意思的字符,比如a,b,c就代表a,b,c
- 元字符:在正则表达式中有特殊含义的非字母字符
* + ?¥ ^ . | \ () {} []
\t 水平制表符
\v 垂直制表符
\n 换行符
\r 回车符
\0 空字符
\f 换页符
\cX 与X对应的控制字符(Ctrl + X)
2.字符类
一般情况下正则表达式一个字符对应字符串一个字符:
- 可以使用元字符
[]
创建一个简单的类 - 类是指符合某些特性的对象,一个泛指,而不是特指某个字符
- 表达式
[abc]
把字符a
或b
或c
归为一类,表达式可以匹配这类的字符
3.字符类取反
- 使用元字符
^
创建反向类/负向类 - 反向类的意思是不属于某类的内容
- 表达式
[^abc]
表示不是字符a或b或c的内容
4.范围类
- 可以使用
[a-z]
来连接两个字符表示从a到z的任意字符 - 闭区间,包含
a
和z
本身 - 在
[]
组成的类内部是可以连着写的[a-zA-Z]
,表示大写和小写字母
5.预定义类
- 匹配常见的字符类
字符 | 等价类 | 含义 |
---|---|---|
. | [^\r\n] | 除了回车符和换行符之外的所有字符 |
\d | [0-9] | 数字字符 |
\D | [^0-9] | 非数字字符 |
\s | [\t\n\x0B\f\r] | 空白符 |
\S | [^\t\n\x0B\f\r] | 非空白符 |
\w | [a-zA-Z_0-9] | 单词字符(字母、数字下划线) |
\W | [^a-zA-Z_0-9] | 非单词字符 |
- 匹配一个ab+数字+任意字符的字符串:
ab\d.
6.边界
常用边界匹配字符:
字符 | 含义 |
---|---|
^ | 以***开始 |
$ | 以***结束 |
\b | 单词边界 |
\B | 非单词边界 |
注意:在不同的场景中部分字符的含义是不同的
比如^
在[]
中是取反,不在就是以***开始
7.量词
字符 | 含义 |
---|---|
? | 出现零次或一次(最多出现一次) |
+ | 出现一次或多次(至少出现一次) |
* | 出现两次或多次(任意次) |
{n} | 出现n次 |
{n,m} | 出现n到m次 |
{n,} | 至少出现n次 |
8.贪婪模式和非贪婪模式
- 贪婪模式:正常情况下
\d{3,6}
会尽可能多的匹配数字,即全部以6为单位匹配(直到没有六个) - 非贪婪模式:让正则表达式尽可能少的匹配,也就是说一旦成功匹配不再继续尝试,以最少的单位匹配
\d{3,6}? 在量词后加?变成非贪婪模式
9.分组
- 正常量词只能匹配到最后一个字母,比如
beyond{3}
,是匹配d字母3次 - 使用()加入分组功能,是量词作用单词,比如
(beyond){3}
- 使用
|
达到或的效果 - 反向引用,巧用
$
分组捕获
10.前瞻
正则表达式从文本头部向尾部开始解析,文本尾部方向称为“前”,前瞻就是在正则表达式匹配到规则的时候,向前检查是否符合断言,后顾方向相反。
名称 | 正则 |
---|---|
正向前瞻 | exp(?=assert) |
负向前瞻 | exp(?!assert) |
断言部分assert也是正则表达式。
三、正则表达式相关的方法
1. 正则对象属性
-
global:是否全文搜索,默认为false
-
ignore case:是否大小写敏感,默认为false
-
multiline:多行搜索,默认值是false
-
lastIndex:是当前表达式匹配内容的最后一个字符的下一个位置,特别注意这个属性,在全局模式
g
下很容易出错,具体看:lastindex属性 -
source:正则表达式的文本字符串
2.正则对象方法
RegExp.prototype.test(str)
- 用于测试字符串参数中是否存在匹配正则表达式模式的字符串
RegExp.prototype.exec(str)
使用正则表达式模式对字符串执行搜索,并将更新全局RegExp对象的属性以反映匹配结果。
- 若没有匹配的文本则返回null
- 否则返回一个结果数组: index:声明匹配文本的第一个字符的位置 input:存放被检索的字符串string
3.字符串对象方法
在字符串方法中可以使用正则表达式
(1)String.prototype.search()
用于检测字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串。 str.search(reg) 返回第一个匹配结果index,没找到返回-1
(2)String.prototype.match()
检索字符串,找到一个或多个与regexp匹配的文本,是否具有g对结果影响很大。
- 若无g,那么match方法只能在字符串中执行一次匹配,返回匹配到的字符串或null
- 有g,返回一个数组,存放匹配到的所有文本的相关信息
(3)String.prototype.replace(reg, replacement)
replace 方法用 replacement 替换对应的匹配,返回替换后的字符串。
replacement 可以是
- 字符串
- 函数,函数的参数是匹配到的字符串 但是不能是箭头函数,因为箭头函数不能取到匹配到的字符串。
下面是几个 replace 的例子:
// 1.get-element变成驼峰式
function commal(str) {
// 不规定个数都是自动匹配一个
// 一定要加全局修饰符
let reg = new RegExp('-[a-z]', 'g')
// $0 是replace匹配到的字符串
// replace方法不改变原有字符串
return str.replace(reg, function($0) {
return $0.slice(1).toUpperCase()
})
}
console.log(commal('ab-gi-du')) // abGiDu
// 2.分割数字每三个以一个逗号划分
function slicestr(str) {
let reg = /\d{3}/
// 这个是正确的,不会出现 123,256, 的情况
//let reg = /(\d)(?=(\d{3})+$)/g;
// 使用箭头函数,取不到 匹配到的字符串,最后返回 undefined
/* return str.replace(reg, (word) => {
word + ','
}) */
return str.replace(reg, function(word) {
return word + ','
})
}
(4)split()方法
四、几个方法的对比
1.RegExp.prototype.test(str) 和 String.prototype.search(reg)
这两个方法都可以用来查找字符串 str 中是否有对应的正则表达式字符串,但有以下不同:
- text 是正则对象的方法,search 是字符串对象的方法
- text 在全局模式下与 RegExp.lastIndex 配合使用,每次都从上一次匹配的位置出发
- text 返回布尔值,只判断是否存在匹配,而 search 返回第一个匹配到的位置,没有则返回 -1
let str = "k is so k"
// 全局模式
let reg = new RegExp("k", "g")
console.log(reg.test(str)) //true
console.log(reg.lastIndex) // 1
console.log(reg.test(str)) //true
console.log(reg.lastIndex) // 9
// 全局模式
let str = "k is so k"
let reg = new RegExp("k", "g")
console.log(str.search(reg)) // 0
console.log(reg.lastIndex) //0
console.log(str.search(reg)) //0
console.log(reg.lastIndex) // 0
2.RegExp.prototype.exec(str) 和 String.prototype.match(reg)
exec 和 match 方法都可以返回有 索引位置index 属性的对象,但两者的具体使用与是否在全局模式下有关系。
- exec 在非全局模式下每次返回第一个匹配对象,在全局模式下和 lastIndex 属性配合使用,每次都向后查找一个,返回对应的匹配对象。
let str = "k is so k"
// 非全局模式
let reg = new RegExp("k")
console.log(reg.exec(str)) // {"0: "k"
// groups: undefined
// index: 0
// input: "k is so k k k"
// length: 1"}
console.log(reg.lastIndex) // 0
console.log(reg.exec(str)) // 同上
console.log(reg.lastIndex) // 0
// 全局模式
let str = "k is so k"
// 非全局模式
let reg = new RegExp("k", "g")
console.log(reg.exec(str)) // {"0: "k"
// groups: undefined
// index: 0
// input: "k is so k"
// length: 1"}
console.log(reg.lastIndex) // 0
console.log(reg.exec(str)) // {"0: "k"
// groups: undefined
// index: 8
// input: "k is so k"
// length: 1"}
console.log(reg.lastIndex) // 9
- match 在全局模式下直接返回 匹配对象数组,没有位置 index 等信息,在非全局模式下返回第一个对象的匹配对象,包含 index 等信息。
// 全局模式
let str = "k is so k"
let reg = new RegExp("k", "g")
console.log(str.match(reg)) // ["k", "k"]
console.log(reg.lastIndex) // 0
console.log(str.match(reg)) // ["k", "k"]
console.log(reg.lastIndex) // 0
// 非全局模式
let str = "k is so k"
let reg = new RegExp("k", "g")
console.log(str.match(reg)) // {"0: "k"
// groups: undefined
// index: 0
// input: "k is so k"
// length: 1"}
console.log(reg.lastIndex) // 0
console.log(str.match(reg)) // 同上
console.log(reg.lastIndex) // 0