正则表达式
正则表达式是一个描述规则的表达式,它可以匹配模式,匹配字符,匹配位置,进而实现搜索和替换功能。
1. 匹配规则
1.1 单个字符
单个字符的映射关系是一对一的,匹配到的字符只有一个。
匹配类型 | 正则表达式 |
---|---|
简单字符 | a (匹配字符a) |
特殊字符 | \* (匹配字符*,特殊字符用\转义) |
换行符 | \n |
换页符 | \f |
回车符 | \r |
空白符 | \s |
制表符 | \t |
垂直制表符 | \v |
回退符 | [\b] |
1.2 区间
[]
来表示集合,用 -
来表示去区间范围,就可以实现一对多的匹配。
/[123]/ 匹配1,2,3中的任意一个字符,/[0-9]/ 匹配0到9的任意一个数字,/[a-z]/ 匹配任意一个英文小写字母。
匹配区间 | 正则表达式 | 记忆方式 |
---|---|---|
集合区间 | [123] | 匹配一个字符,可以是1,2,3之一 |
通配符,表示几乎任意字符。换行符、回车符、行分隔符和段分隔符除外。 | . | |
单个数字,[0-9] | \d | digit |
除了[0-9] | \D | not digit |
包括下划线在内的单个字符[A-Za-z0-9] | \w | word |
非单字字符 | \W | not word |
匹配空白符,包括空格、制表符、换行符和换页符 | \s | space |
匹配非空白字符 | \S | not space |
匹配任意字符 | [\d\D]、[\w\W]、[\s\S] |
1.3 量词
多次循环,重复上面的正则规则,就可以匹配匹配多个字符。
符号 | 重复次数 | 例子 | |
---|---|---|---|
? | 0次或1次 | /colour?/ | 匹配colou和colour两个单词 |
+ | 1次或多次 | /color+/ | 匹配color, colorr, colorrr… |
{n} | 区间次数 | /a{3}/ | 连续出现a 3次 |
{min,max} | min到max次 | /a{1,2}/ | 连续出现a 1-2次 |
{min,} | 至少min次 | /a{1,}/ | 连续出现a至少1次 |
{0, max} | 最多max次 | /a{0,3}/ | 连续出现a最多3次 |
* | 匹配0个字符或无数个字符 | /*/ | 用来过滤可有可无的字符串 |
1.5 位置符
位置是相邻字符之间的位置。
符号 | 含义 | 例子 | |
---|---|---|---|
\b | 单词边界,\w和\W之间的位置,也包括\w和^,\w和$之间的位置 | /\bcat\b/ | 匹配cat,匹配不到scattered |
^ | 匹配开头,在多行匹配中匹配开头 | /^I am/ | 以I am开头的字符串 |
$ | 匹配结尾,在多行匹配中匹配结尾 | /^I am good.$/ | 匹配I am good这个句子 |
(?=p) | p是一个子模式,表示p前面的位置 | /(?=l)/g | 所有l前面的位置 |
(?!=p) | (?=p)的反面意思 |
1 | "hello".replace(/^|$/g, '#') // "#hello#" |
1.4 分组,回溯引用
() 表示一个分组,只是使用简单的(regex)本质上和不分组是一样的,要发挥它强大的作用,要结合回溯引用。
\1, \2....
表示引用的第1,2个子表达式… \0
表示整个表达式。回溯引用 指后面引用前面已经匹配到的子字符串。
$1, $2...
用于引用要被替换的字符串1
2
3
4var reg = /\b(\w)+\s\1/ // 匹配两个连续相同的单词
var str = 'abc abc 123';
str.replace(/(ab)c/g, '$1g'); // 'abg abg 123'
$&
匹配子串文本1
2// '2,3,5'变成'222,333,555'
"2,3,5".replace(/(\d)+/g, $&$&$&); // 222,333,555
(?:regex)
,如果我们不想子表达式被引用,可以用非捕获正则, 这样可以避免浪费内存。1
2
3var str = 'scq000';
str.replace(/(scq00)(?:0)/, '$1,$2'); // 'scq00,$2'
// 使用了非捕获正则,所以第二个引用没有值,这里直接替换为$2
1.5 逻辑处理
逻辑关系 | 正则表达式 |
---|---|
与 | 无 |
非 | [^regex] 和 ! |
或 | | |
1.6 修饰符
修饰符放在了/regex/img
正则表达式的最后面。
修饰符 | |
---|---|
m | 多行匹配 multiline |
i | 忽略大小写 ignore |
g | 全局匹配global, 在目标字符串中按顺序找到满足匹配模式的所有子串 |
1 | var regex = /ab{2,4}c/g |
2. 正则表达式 + JS
有了正则表达式进行匹配,结合JS api,我们可以完成验证、切分、提取、替换的动作。1
2
3
4
5
6String.search(regex)
String.split(regex)
String.match(regex)
String.replace(regex, newText)
RegExp.test(string)
RegExp.exec(string)
2.1 验证
判断有没有匹配上1
2
3
4
5
6// 判断一个字符串中有没有数字
var regex = /\d/;
var string = "abc123";
// 最常用的是test
console.log(regex.test(string)); // true
2.2 切分
把目标字符串,切成一段一段 string.split(regex)
1
2
3
4
5// 日期格式切除年月日
var regex = /\D/;
console.log("2017-01-01".split(regex)); // ["2017", "01" "01"]
console.log("2017.01.01".split(regex)); // ["2017", "01" "01"]
console.log("2017/01/01".split(regex)); // ["2017", "01" "01"]
2.3 提取
提取匹配到的数据1
2
3
4
5var regex = /^(\d{4})\D(\d{2})\D(\d{2}))$/;
var string = "2017-06-26";
string.match(regex);
// [$0, $1, $2 ... , index, input]
// =>["2017-06-26", "2017", "06", "26", index: 0, input: "2017-06-26"]
2.4 替换
string.replace(regex, newtext)
1
2
3
4// 将yyyy-mm-dd替换成yyyy/mm/dd
var string = "2017-06-26";
var today = new Date( string.replace(/\-/g, "/"))
console.log(today) // => Mon Jun 26 2017 00:00:00 GMT+0800 (中国标准时间)
3. 匹配原理
3.1 回溯
后补
3.2 操作符优先级
优先级从上至下,由高到低
- 转义符 \
- 括号和方括号 (…)、(?:…)、(?=…)、(?!…)、[…]
- 量词限定符 {m}、{m,n}、{m,}、?、*、+
- 位置和序列 ^ 、$、 \元字符、 一般字符
- 管道符(竖杠)|
3.3 优化效率
后补
4. 例子
1 | var regex = /hello/; |
5. 没有必要用正则的情况
1 | // 从日期中提取年月日 |