一个字符串,由字符和位置组成,正则世界的奥妙离不开这两者。以下将围绕字符的要点进行说明。
1 字符
常见元字符:具体含义的单个字符,如123...、abc...、ABC...、标点符号等等;
字符组合的含义是,匹配一个元字符,可以是多种可能之一;
1.1 范围表示法
在实际应用中,通常会将一类元字符一起应用,比如数字、字母等等,如果一个个书写很麻烦,就可以用范围表示法;
比如 [123456789] 表示为 [1-9],通过 连字符- 来简写;
问题1:既然在范围通过连字符连接,如何在其中使用连字符本身的含义?
将连字符放在
开头、结尾,或者转义即可,比如:[-1-9]、[1-9-]、[1-9];
问题2:范围表示法最终只会匹配一个字符,如何匹配一个范围中的多个字符串?
通过利用分支分隔子表达式,比如 /strq|strw|stre/;
1.2 排除表示法
有正即有反,有时也会遇见将某些字符排除在外的场景,这时可以利用 脱字符^,比如 [^abc],表示除了a、b、c之外的任一字符;
问题3:同样的,如何排除某些字符串?
1、
[^(rengar)]不行,范围只会匹配单字符;
2、^(renagr)不行,脱字符在范围外,表示着起始位置;
3、可以通过((?!rengar).)+,(?!rengar)匹配位置,该位置后,不能有字符串rengar,再接上通配符匹配字符;
1.3 常见的简写字符组
| 字符组 | 具体含义 |
|---|---|
| \d | 等同 [0-9],表示一位数字,记忆:digit |
| \D | 等同 [^0-9],表示一位非数字 |
| \w | 等同 [a-zA-Z0-9_],表示数字、大小写字母、下划线,记忆:word |
| \W | 等同 [^a-zA-Z0-9_] |
| \s | 等同 [\t\v\n\r\f],表示空格、水平制表符、垂直制表符、换行符、回车符、换页符,记忆:space |
| \S | 等同 [^\t\v\n\r\f] |
| . | 等同 [^\n\r\u2028\u2029],通配符,代表几乎所有字符,除了换行符、回车符、行分隔符、段分隔符 |
问题4:通配符不代表所有字符,如何表示所有字符?
通过
[\d\D]、[\w\W]、[\s\S]、[^]表示; tips:[^.],在范围表示法中使用通配符.只会表示它本身的含义,即字符.;
2 重复
通过类似 {m,n} 的形式,匹配长度不固定的字符串,比如 /ab{2,4}c/,可视化表示如下;
理解重复:对于元字符来说,除非加上重复标识,或者全局匹配修饰符g,匹配的都是一个字符;
2.1 重复常用简写
| 重复 | 具体含义 |
|---|---|
| {m} | 出现过m次 |
| {m,} | 至少出现过m次 |
| {m,n} | 至少出现过m次,至多n次 |
| ? | 等同 {0,1} |
| + | 等同 {1,} |
| * | 等同 {0,} |
2.2 贪婪和懒惰模式
正则在匹配时,会尽可能多的匹配字符,这就是我们说的贪婪,比如:
var regexp = /\d{2,5}/g;
var string = "12 123 1234 12345 123456";
console.log( string.match(regexp) );
// ["12", "123", "1234", "12345", "12345"]
但是,有时候贪婪并不是一件好事,这时通过懒惰模式去匹配(在后面加一个 问号? ,知足了吗);
var regexp = /\d{2,5}?/g;
var string = "12 123 1234 12345 123456";
console.log( string.match(regexp) );
// ['12', '12', '12', '12', '12']
3 分支
通过管道符“|” 分隔多个子表达式,匹配其中一种可能性;比如 (p1|p2|p3);
对比 范围选择[],可以进行字符串的匹配;
var regexp = /a[123]c/g;
var string = "ac a1c a2c a3c a123c";
console.log( string.match(regexp) );
// ['a1c', 'a2c', 'a3c']
如果使用 /good|goodbye/ 去匹配的呢?
结果是匹配 "good",分支当前面的匹配上了,后面不会再尝试;
var regexp = /good|goodbye/g;
var string = "goodbye";
console.log( string.match(regexp) );
// ['good']
4 概念整理
| 名词 | 含义 |
|---|---|
| 元字符 | 具体含义的单个字符; 如123...、abc...、ABC...、标点符号等等; |
| 字符组 | 匹配一个元字符,可以是多种可能之一; 如 [1-9]; |
| 子表达式 | 多个元字符组成的字符串组合; |
| 重复 | 一个元字符、字符组连续出现; 如 /ab{2,4}c/; |
| 分支 | 分隔多个子表达式,匹配其中一种可能性; 如 p1|p2|p3; |
| 编组 | 通过括号将字符串进行编组; |
| 位置 | 字符间相邻的点; |
最后,感谢《正则表达式必知必会》、《JavaScript正则表达式迷你书》等作者带来的启示,在这里梳理自己理解和相关的扩展,总结出来。