一.什么是正则表达式
正则表达式就是一种表达文本模式(即字符串结构)的方法,有点像字符串的模板,常常用来按照“给定模式”匹配文本
简而言之就是是一种模板,用这个模板来匹配字符串
二.如何创建一个表达式
-
使用字面量
var reg = /xy/igm;
xy表示要匹配的字符串
igm是修饰符,意思分别是
i ---- ignoreCase 忽略大小写
g ----global 全局匹配
m ---- multiline 多行匹配 -
使用RegExp()构造函数
var reg = new RegExp(‘xy’,‘igm’);
两种方式是一样的,区别是 字面量的方式在编译时创建表达式,构造函数是在运行时创建表达式,因此字面量的效率高一些,建议使用字面量
三.实例属性,方法及匹配规则
- 实例属性
修饰符有关
ignoreCase 返回值 true/false ,是否设置了 i 标识符
global 返回值 true/false ,是否设置了 g 标识符
multiline 返回值 true/false ,是否设置了 m 标识符
flags 返回值 是该正则表达式所设置的标识符 ,按照字母排序
修饰符无关
lastIndex 下一次开始搜索的位置
source 返回正则表达式的字符串形式,不包括 //
var regex = /xy/ig;
// 等同于
// var regex = new RegExp('xy','ig');
// !!!!实例属性
// 1.修饰符相关 只读
// true 正则表达式是否设置了 i 属性
console.log('regex.ignoreCase',regex.ignoreCase);
// true 正则表达式是否设置了 g 属性
console.log('regex.global',regex.global);
// false 正则表达式是否设置了 m 属性
console.log('regex.multiline',regex.multiline);
// 正则表达式的所有已设置的属性,按字母排序
console.log('regex.flags',regex.flags);
// 2.修饰符无关
// 0 下次搜索开始的位置 可读写 lastIndex下一次开始搜索的位置
console.log('regex.lastIndex',regex.lastIndex);
// 'xy',string source 返回正则表达式的字符串形式,不包括 反斜杠,只读
console.log('regex.source,typeof regex.source',regex.source,typeof regex.source);
- 实例方法
正则表达式里的实例方法
test() 检查字符串里是否有满足正则表达式的字符串,返回值是 true/false
exec() 返回的是符合 正则表达式的字符串 数组,否则返回 null
exec() 返回的数组里还包括---- index 匹配成功开始的位置 ----input 原字符串
字符串里关于正则表达式的实例方法
match() 返回的是符合正则表达式的字符串数组,否则返回 null,与exec()类似,不同之处在于 当含有 g 修饰符时,match()返回的是所有匹配的子字符串,每次匹配都是从头开始,而exec()则是每次匹配一个
search() 返回的是字符串开始匹配成功的下标,否则返回-1
replace() 返回的是替换后的字符串,参数1是需要替换的内容,参数2是替换的内容
split() 返回的是 分隔符分割后的字符串数组
//!!!!实例方法
// test()检查字符串里是否有满足正则表达式的字符串,返回值是 true/false
// ture
console.log('test()',/cat/.test('cats and dogs'));
// 正则表达式为空,则匹配所有字符串
// true
console.log('new RegExp("")',new RegExp('').test('this is a test'));
// exec()返回的是符合 正则表达式的字符串 数组,否则返回 null
// index 整个模式首先匹配成功的开始位置
// input 原字符串
// ['cat']
var reg = /cat/ig;
console.log('exec()',reg.exec('cat and bat and Cat'));
// ['Cat'] 使用了 g ,记录了上次匹配结束的位置
// 当匹配结果为 null 时,下一次匹配会重头开始 ,lastIndex 会重置为0
console.log(reg.exec('cat and bat and Cat'));
// !!!! 字符串中关于正则表达式的实例方法
// match() 返回的是数组,成员是所有匹配的子字符串,否则返回null,与 exec() 类似
// 不同: 当含有 g 修饰符时,返回的是所有匹配的子字符串,每次匹配都是从头开始
// ['cat']
console.log('match()','cat and bat and Cat'.match(/cat/ig));
// search() 返回的是整数,表示第一个匹配开始的位置,否则返回 -1
// 0
console.log('search()','cat and bat and Cat'.search(/cat/));
// repalce() 返回的是替换后的字符串 ,参数1 是需要替换的内容, 参数2 是替换的内容
// dog and bat and Cat
console.log('replace()','cat and bat and Cat'.replace(/cat/,'dog'));
// dog and bat and dog
console.log('replace()','cat and bat and Cat'.replace(/cat/ig,'dog'));
// split() 以分隔符返回分隔字符串后的数组
// 正则默认是贪婪匹配
// [ "c", "t ", "nd b", "t ", "nd C", "t" ]
console.log('split()','cat and bat and Cat'.split(/a/));
// [ "c", "a", "t ", "a", "nd b", "a", "t ", "a", "nd C", "a","t"]
// 如果正则表达式里有 括号 ,则括号里匹配的内容也会返回
console.log('split()','cat and bat and Cat'.split(/(a)/));
- 匹配规则
-
字面量字符,字符就是它本身没有其他含义
-
元字符,有特殊含义的字符
- 点字符(.)
可以匹配除 回车(\r) 换行(\n) 行分隔符(\u2028) 段分隔符(\u2029) 以外的所有字符,一个点字符 匹配一个字符
// [ "cat", "cbt", "cct", "c t", "c=t" ]
console.log('点字符','cat cbt cct cddt c t c=t'.match(/c.t/g));
// ["cddt"]
console.log('两个点字符','cat cbt cct cddt c t c=t'.match(/c..t/g))
- 位置字符(^ $)
字符出现的位置
^ 字符串的开始位置
$ 字符串的结束位置
// null
console.log('^ match()','at cbt cct cddt c t c=t'.match(/^cat/));
// true
console.log('^ test()',/^cat/.test('cat cbt cct cddt c t c=t'));
// ["c=t"]
console.log('$ match','cat cbt cct cddt c t c=t'.match('c=t$'));
// true
console.log('$ test()',/c=t$/.test('cat cbt cct cddt c t c=t'));
// true /^cat$/表示字符串只能是 cat
console.log("^ $",/^cat$/.test('cat'));
// false
console.log("^ $",/^cat$/.test('cat cat'));
-
选择符(|)
或关系,匹配其中一个, | 会匹配前后的多个字符,要想只匹配指定的字符个数可以使用 圆括号
比如/ab|cd/指的是匹配ab或者cd,而不是指匹配b或者c。如果想修改这个行为,可以使用圆括号。
/a( |\t)b/.test(‘a\tb’) true 代码指的是,a和b之间有一个空格或者一个制表符。 -
转义符(\)
有特殊含义的字符想要匹配自身时必须使用转义字符
正则表达式中需要转义的字符有12个 ^ $ . ( ) [ | * + ? {
注意 使用RegExp函数生成正则表达式时,需要加 两个斜杠, 因为字符串内部会先转义一次
// 报错 missing ) after argument list
// console.log('\',new RegExp('1\.1').test('1.1'));
// true
console.log('RegExp',new RegExp('1\\.1').test('1.1'));
- 特殊字符
正则表达式对一些不能打印的特殊字符,提供了表达方法。
\cX 表示Ctrl-[X],其中的X是A-Z之中任一个英文字母,用来匹配控制字符。
[\b] 匹配退格键(U+0008),不要与\b混淆。
\n 匹配换行键。
\r 匹配回车键。
\t 匹配制表符 tab(U+0009)。
\v 匹配垂直制表符(U+000B)。
\f 匹配换页符(U+000C)。
\0 匹配null字符(U+0000)。
\xhh 匹配一个以两位十六进制数(\x00-\xFF)表示的字符。
\uhhhh 匹配一个以四位十六进制数(\u0000-\uFFFF)表示的 Unicode 字符。 - 字符类([])
表示有一列字符可供选择,只要匹配其中一个就可以了
6.1 脱字符 (^ 只有在字符类的第一个位置才有特殊含义)
[^] 表示除了 字符类之外的其他字符都可以匹配,包括换行符 例如[^xyz]表示除了 x,y,z 剩下的都可以匹配
6.2 连字符(-)(匹配前后的一个字符)
连续序列的字符 的简写,只包含前后的一个字符 如 [1-9] 表示1,2,3…9
// false 字符串中没有 abc 的任意一个
console.log('字符类 test()',/[abc]/.test('ddddddddddddd'));
// true 字符串中出现了 a
console.log('字符类 test()',/[abc]/.test('adddddddddddd'));
// 6.1 脱字符 (^ 只有在字符类的第一个位置才有特殊含义)
// [^] 表示除了 字符类之外的其他字符都可以匹配,包括换行符 例如[^xyz]表示除了 x,y,z 剩下的都可以匹配
// true
console.log('[^]',/[^cat]/.test('cat bdefghijklmnopqrsuvwxyz'));
// false 除了 cat 在没其他字符因此 false
console.log('[^]',/[^cat]/.test('catcatcatcatcatatatcatat'));
// 换行符
// false 点字符不能匹配换行符
console.log('换行符使用 . 匹配',/good.*day/.test('today is a good\n day'));
// true [^]可以匹配换行符
console.log('换行符使用 [^] 匹配',/good[^]*day/.test('today is a good\n day'));
// 6.2 连字符(-)
// 连续序列的字符 的简写,只包含前后的一个字符 如 [1-9] 表示1,2,3...9
// false
console.log('-不在[]里',/a-c/.test('abc'));
// true
console.log('-在[]里',/[a-c]/.test('abc'));
// 注意 [1-31] 表示 1-3
- 预定义模式
常见模式的简写
\d 表示0-9的任一数字,相当于 [0-9]
\D 表示除0-9之外的所有字符,相当于 [^0-9]
\w 表示匹配任意的字母,数字,下划线,相当于 [0-9a-zA-Z_]
\W 表示除字母,数字,下划线之外的所有字符,相当于 [^0-9a-zA-Z_]
\s 匹配空格(包括换行符,制表符,空格符等等),相当于 [\t\r\n\v\f]
\S 匹配非空格的字符,相当于 [^\t\r\n\v\f]
\b 匹配词的边界,在匹配的开始则 只有该字符串在词首独立时才能匹配成功,在匹配的结束则 只有该字符串在词尾独立时才能匹配成功
\B 匹配非词边界,即在词的内部
// \b 的例子
/\bworld/.test('hello world') // true
/\bworld/.test('hello-world') // true
/\bworld/.test('helloworld') // false
// \B 的例子
/\Bworld/.test('hello-world') // false
/\Bworld/.test('helloworld') // true
- 重复类({})
模式的精确匹配次数
{n} 恰好重复n次
{n,} 至少重复n次
{n,m} n <= 重复次数 <= m
// 指定 c 出现 2~6 次
console.log('{n,m}',/abc{2,6}d/.test('abcccdd'));
- 量词符
设置某个模式出现的次数
? 0 或 1,{0,1}
* 0 或 多次,{0,}
+ 1 或 多次,{1,} - 贪婪模式
默认情况下最大可能匹配,即匹配到下一个规则不满足为止
?? 匹配 0 或 1,采用非贪婪模式
*? 匹配 0 或 多,采用非贪婪模式
+? 匹配 1 或 多,采用非贪婪模式
// [ "aaaaaa" ]
console.log('贪婪模式',/a*/.exec('aaaaaab'));
// 改 为非贪婪模式
// ?? 匹配 0 或 1,采用非贪婪模式
// *? 匹配 0 或 多,采用非贪婪模式
// +? 匹配 1 或 多,采用非贪婪模式
// [ "" ]
console.log('?? 非贪婪模式',/a??/.exec('aaaaaab'));
// [ "" ]
console.log('*? 非贪婪模式',/a*?/.exec('aaaaaab'));
// [ "a" ]
console.log('+? 非贪婪模式',/a+?/.exec('aaaaaab'));
- 组匹配( () )
正则表达式中使用圆括号(),则返回的数组会包含多个成员。第一个成员是整体匹配的结果,第二个是第一个圆括号里匹配的结果,第三个是第二个圆括号里匹配的结果
正则表达式内部还可以用 \n 引用括号匹配的内容 n 是从 1 开始的自然数
例如 \1 表示第一个括号匹配的内容
// true \1匹配的是 a \2匹配的是 c
console.log('组匹配里 \n',/(.)b(.)\1b\2/.test('abcabc'));
- 非捕获组(?:x)
能匹配,但不返回该组匹配的内容,即 x
// [ "abcabc", "abc" ]
console.log('非捕获组','abcabc'.match(/(abc){1,2}/));
// [ "abcabc" ]
console.log('非捕获组','abcabc'.match(/(?:abc){1,2}/))
- 先行断言(x(?=y))
x只有在 y 前面才会被匹配,y 不会计入返回结果
// null
console.log('先行断言','a不在c的前面','abc'.match(/a(?=c)/));
// [ "a" ]
console.log('先行断言','a在c的前面','ac'.match(/a(?=c)/));
- 先行否定断言(x(?!y))
x 只有不在 y 前面才会被匹配
// null
console.log('先行否定断言','a在c的前面','ac'.match(/a(?!c)/));
// [ "a" ]
console.log('先行否定断言','a不在c的前面','bca'.match(/a(?!c)/));