1. 修饰符
g:global 全文搜索,如果不添加,则搜索到第一个匹配时停止i:ignoreCase 忽略大小写,默认大小写敏感m:multiline 多行匹配
2. 元字符
正则表达式由两种基本字符类型组成:
- 原义文本字符
- 元字符
元字符是在正则表达式中有特殊含义的非字母字符,包含:
\:转义,将具有特殊意义的元字符转成原义文本字符.:除了换行以外的所有字符+:至少一个,一次或者多次?:至多一次,零或者一次*:任意次$:以 … 结尾^:字符类取反、或者以 … 开头|:或():分组{}:用来包裹量词范围[]:用来包裹字符类 | 字符 | 含义 | | —- | —- | | \t | 水平制表符 | | \v | 垂直制表符 | | \n | 换行符 | | \r | 回车符 | | \0 | 空字符 | | \f | 换页符 | | \cX | 与X对应的控制字符(Ctrl+X) |
3. 字符类
一般情况下,正则表达式一个字符对应一个字符,如 ab\t,表示字符 ‘ab’ 以及一个制表符 tab
如果我们需要匹配一类字符,可以使用元字符 [] 来构建一个简单的类。所谓的类是指符合某些特性的对象,是一个泛指。如 [abc] 把字符 a 或 b 或 c 归为一类,只要有里面的一个,就能匹配。
'a1b2c3c'.replace(/[abc]/g, 'X'); // 'X1X2X3X'
中括号中出现的元字符一般都是代表本身含义的
let reg = /^[.]+$/;reg.test('.'); //=> true
中括号中的 - 有特殊含义,一般需要放在后面或者前面来代表本义
中括号中出现两位数,不是两位数,而是代表两个数中的任意一个
let reg = /^[12-65]$/g //=> 表示 1 或者 2-6 或者 5
3.1 字符类取反
使用元字符 ^ 创建反向类/负向类,就是不属于某类的内容。如 [^abc] 表示不是字符 a 或 b 或 c 的内容。
'a1b2c3c'.replace(/[^abc]/g, 'X'); // 'aXbXcXc'
3.2 范围类
使用 - 来连接两个字符,如 [a-z] 表示从 a 到 z 的任意字符,这是一个闭区间,包含 a 和 z 本身。
'a1b2d3x4z9'.replace(/[a-z]/g, 'Q'); // 'Q1Q2Q3Q4Q9'
在 [] 组成的类内部是可以连写的,如 [a-zA-Z]
注意:横线并不是元字符,但是在上面的情况是特指范围,不会匹配到 -
。如果需要匹配到横线,只需要在后面再加上横线。[a-z-]表示 a 到 z 以及横线。
3.3 预定义类
正则表达式提供预定义类来匹配常见的字符类。
| 字符 | 等价类 | 含义 |
|---|---|---|
| . | [^\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] | 非单词字符 |
4. 边界
正则表达式还提供了几个常用的边界匹配字符
^:以……开始$:以……结束\b:单词边界\B:非单词边界
// 开头结尾匹配'@12@12@1'.replace(/@./g, '0'); // '02020''@12@12@1'.replace(/^@./g, '0'); // '02@12@1''@12@12@1'.replace(/@.$/g, '0'); // '@12@120'// 多行开头结尾匹配‘@12@12@12’.replace(/^@./g, '0');// '02// @12// @12'‘@12@12@12’.replace(/^@./gm, '0');// '02// 02// 02'// 单词边界'This is a boy'.replace(/is/g, '0'); // 'Th0 0 a boy''This is a boy'.replace(/\bis\b/g, '0'); // 'This 0 a boy''This is a boy'.replace(/\Bis\b/g, '0'); // 'Th0 is a boy'
5. 量词
?:出现零次或者一次(最多一次)+:出现一次或多次(至少出现一次)*:出现零次或者多次(任意次){n}:出现 n 次{n,m}:出现 n 到 m 次{n,}:至少出现 n 次
注意:量词只作用于紧挨它的前一个正则字符
贪婪模式:正则表达式会在范围允许内尽可能多的匹配。
非贪婪模式:让正则表达式尽可能少的匹配,一旦匹配成功就不再继续匹配。
默认正则表达式都是贪婪模式。如果需要实现非贪婪模式,只需要在量词后加上 ? 即可。
// 贪婪模式'123456789'.replace(/\d{3,6}/g, 'X'); // 'X78'// 非贪婪模式'123456789'.replace(/\d{3,6}?/g, 'X'); // 'XX78'
6. 分组
如果要匹配 destiny 连续出现的场景,如果使用 destiny{3},那么只会匹配到 destinyyy,而不是 destinydestinydestiny。
这时就需要使用 () 分组,使量词作用于分组。(destiny){3}
分组的作用:
- 提升优先级
- 分组匹配,可以理解成大正则里边的小正则
- 分组捕获
let reg = /^1|8$/'1' //=> true'8' //=> true'18' //=> true//=> 以 18 开头或 19 结束let reg = /^18|19$/;'18'; //=> true'19'; //=> true'1819'; //=> true'181'; //=> true'819'; //=> true'189'; //=> true'119'; //=> true//=> 如果只是想要匹配 18 或 19let reg = /^(18|19)$/
6.1 或
使用 | 可以达到或的效果
'ByronCasper'.replace(/Byron|Casper/g, 'X'); // 'XX''ByronsperByrCasper'.replace(/Byr(on|Ca)sper/g, 'X'); // 'XX
6.2 分组捕获
分组后,可以使用 $1 - $n 来表示各个分组匹配到的内容。即可以把分组内的内容捕获到。
'2018-05-11'.replace(/(\d{4})-(\d{2})-(\d{2})/g, '$2/$3/$1'); //=> 05/11/2018
6.3 分组引用
正则中,使用 \1、\2 等,来引用正则中出现的分组捕获的内容
//=> 匹配到四个字符的字母,其中第一个与最后一个一样,第二位与倒数第二位一样let reg = /^([a-Z])([a-Z])\2\1¥/;'oppo' //=> true'abba' //=> true
6.4 忽略分组
如果不希望捕获某些分组,只需要在分组内加上 ?:就可以,如 (?:Byron).(ok),这时,$1 就捕获 ok 分组匹配的内容
7. 前瞻
正则表达式从文本头部向尾部开始解析,称为“前”。
前瞻就是在正则表达式匹配到规则中的时候,向前检查是否符合断言,后顾方向相反。JavaScript 不支持后顾。
符合和不符合特定断言称为肯定/正向匹配和否定/负向匹配
| 名称 | 正则 |
|---|---|
| 正向前瞻 | exp(?=assert) |
| 负向前瞻 | exp(?!assert) |
正向前瞻:例 \w(?=\d),在是单词的基础上向前判断后面紧跟的是否是数字,这里只匹配单词,后面括号内的只是判断单词是否符合条件。
'a2*3'.replace(/\w(?=\d)/g, 'X'); // 'X2*3''a2*34v8'.replace(/\w(?=\d)/g, 'X'); // 'X2*X4X8'
负向前瞻:例 \w(?!\d),在单词的基础上向前判断后面紧跟的是否不是数字,这里也是只匹配单词,后面的只是判断条件。
'a2*3'.replace(/\w(?!\d)/g, 'X'); // 'aX*3''a2*34v8'.replace(/\w(?!\d)/g, 'X'); // 'aX*3XvX'
