之前是写在另一个平台,但更新的断断续续,这次打算回炉重造,整理一波。
两种方式:
// 使用正则表达字面量
var regex = /ab+c/;
// 使用RegExp对象的构造函数
var regex = new RegExp("ab+c");
正则表达式的精髓,主要在与它的模糊。先来看一个基础小例子:
var regex = /hello/;
console.log(regex.test("hello"));
// => true
var string = 'Hi, hello world';
console.log(string.match(regex));
// => ["hello", index: 4, input: "Hi, hello world", groups: undefined]
2.1 量词匹配
{m,n}
,表示连续出现最少m次,最多n次。
例如:/ab{2,5}c/
表示:第一个字符是“a”,第2到5个字符“b”,最后是字符“c”。
这里可以看出{m,n}
作用的是前面的那个字符,即b。
var regex = /ab{2,5}c/g;
var string = "abc abbc abbbc abbbbc abbbbbc abbbbbbc";
console.log(string.match(regex));
// => ["abbc", "abbbc", "abbbbc", "abbbbbc"]
注意:示例中的/g
表示全局匹配,即在目标字符串中按顺序找到满足匹配模式的所有子串,强调的是“所有”,而不只是“第一个”。
量词表示匹配的字符或表达式的数量,下表中是一些简单常用的形式:
字符 |
含义 |
|
n 和 m 都是整数。匹配前面的字符至少 m 次,最多 n 次。如果 n 或者 m 的值是0, 这个值被忽略。 例如,/a{1, 3}/ 并不匹配“cndy”中的任意字符,匹配“candy”中的a,匹配“caandy”中的前两个a,也匹配“caaaaaaandy”中的前三个a。注意,当匹配”caaaaaaandy“时,匹配的值是“aaa”,即使原始的字符串中有更多的a。 |
|
m是一个正整数,匹配前一个字符至少出现了m次。 例如, /a{2,}/ 匹配 "aa", "aaaa" 和 "aaaaa" 但是不匹配 "a"。 |
|
m 是一个正整数,匹配了前面一个字符刚好出现了 m 次。等价于 比如, /a{2}/ 不会匹配“candy”中的'a',但是会匹配“caandy”中所有的 a,以及“caaandy”中的前两个'a'。 |
|
匹配前面一个表达式 0 次或者 1 次。等价于 例如, 如果紧跟在任何量词 *、 +、? 或 {} 的后面,将会使量词变为非贪婪(匹配尽量少的字符),和缺省使用的贪婪模式(匹配尽可能多的字符)正好相反。例如,对 "123abc" 使用 |
|
匹配前面一个表达式 1 次或者多次。等价于 例如, |
|
匹配前一个表达式 0 次或多次。等价于 例如, |
2.2 字符组匹配
[abc]
,表示表示匹配一个字符,可以是字符‘a’、‘b’、‘c’中的任何一个。
比如/a[123]b/
可以匹配如下三种字符串:"a1b"、"a2b"、"a3b"。
var regex = /a[123]b/g;
var string = "a0b a1b a2b a3b a4b";
console.log(string.match(regex));
// => ["a1b", "a2b", "a3b"]
问:如果字符组里的字符特别多,怎么办?
答:可以使用范围表示法。比如[123456abcdefGHIJKLM]
,可以写成[1-6a-fG-M]
。用连字符-
来省略和简写。
问:因为连字符有特殊用途,如果要匹配“a”、“-”、“z”这三者中任意一个字符,怎么办?
答:不能写成[a-z]
,因为其表示小写字符中的任何一个字符。可以写成如下的方式:[-az]
或[az-]
或[a\-z]
。三条路:开头、结尾、转义。
问: 如果我想要的匹配的字符是除了a/b/c三个字符之外的,怎么办?
答:使用反向字符集。例如[^abc]
,表示除"a"、"b"、"c"之外的任意一个字符。字符组的第一位放^
,表示取反。当然,也可以使用范围表示。
关于字符组常见的简写形式,引用MDN上的常用的字符符号:
字符 |
含义 |
\d |
等价于 例如, |
\D |
等价于 例如, |
\w |
等价于 例如, |
\W |
等价于 例如, |
\s |
匹配一个空白字符,包括空格、制表符、换页符和换行符。 例如, 经测试,\s不匹配"\u180e",在当前版本Chrome(v80.0.3987.122)和Firefox(76.0.1)控制台输入/\s/.test("\u180e")均返回false。 |
\S |
匹配一个非空白字符。 例如, |
. |
(小数点)默认匹配除换行符之外的任何单个字符。 例如, 如果 |
问:如果要匹配任意字符怎么办?
答:可以使用[\d\D]
、[\w\W]
、[\s\S]
和[^]
中任何的一个。
再来看两个小例子吧:
var regex = /\d{2,5}/g;
var string = "123 1234 12345 123456";
console.log(string.match(regex));
// => ["123", "1234", "12345", "12345"]
其中正则/\d{2,5}/
,表示数字连续出现2到5次。会匹配2位、3位、4位、5位连续数字。这个例子的特点就是:尽可能的多匹配。换句话说,就是贪婪。
而加上问号的它,就会尽可能少的匹配:
var regex = /\d{2,5}?/g;
var string = "123 1234 12345 123456";
console.log( string.match(regex) );
// => ["12", "12", "34", "12", "34", "12", "34", "56"]
其中/\d{2,5}?/
表示,虽然2到5次都行,当两个可以的时候,就不往下面匹配了。
因此,量词后面加问号,也可以理解为有人问你:够了不?够了就行了。适可而止。
具体形式如下:(p1|p2|p3)
,其中p1
、p2
和p3
是子模式,用|
(管道符)分隔,表示其中任何之一。
例如要匹配"happy"和"hobby"可以使用/happy|hobby/
。测试如下:
var regex = /happy|hobby/g;
var string = "happy time, hobby";
console.log( string.match(regex) );
// => ["happy", "hobby"]
但是,比如我用/hello|helloWorld/
,去匹配"helloWorld
"字符串时,结果是"hello
":
var regex = /hello|helloWorld/g;
var string = "helloWorld";
console.log( string.match(regex) );
// => ["hello"]
而把正则改成/helloWorld|hello/
,结果是:
var regex = /helloWorld|hello/g;
var string = "helloWorld";
console.log( string.match(regex) );
// => ["helloWorld"]
同上面的?
效果一样,即当前面的匹配上了,后面的就不再尝试了。
注意,每个正则并不是只有唯一写法:
4.1 匹配16进制颜色值
要求匹配:
#ff8040
#d1d3D8
#F4F6F9
#fffEEF
#FFF
分析:
表示一个16进制字符,可以用字符组
[0-9a-fA-F]
。其中字符可以出现3或6次,需要是用量词和分支结构。
使用分支结构时,需要注意顺序。
正则如下:
var regex = /#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})/g;
var string = "#ff8040 #d1d3D8 #F4F6F9 #fffEEF #FFF";
console.log(string.match(regex));
// => ["#ff8040", "#d1d3D8", "#F4F6F9", "#fffEEF", "#FFF"]
4.2 匹配日期
比如yyyy-mm-dd格式为例。
要求匹配:
2020-11-19
分析:
年,四位数字即可,可用
[0-9]{4}
。月,共12个月,分两种情况01、02、……、09和10、11、12,可用
(0[1-9]|1[0-2])
。日,最大31天,可用
(0[1-9]|[12][0-9]|3[01])
。
正则如下:
// 注意:此正则没有对2月和30、31号做单独的校验处理
var regex = /^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/;
console.log(regex.test("2017-06-10"));
// => true
// 关于$: 匹配输入的结束。如果多行标志被设置为 true,那么也匹配换行符前的位置。
// 例如,/t$/ 并不会匹配 "eater" 中的 't',但是会匹配 "eat" 中的 't'。
// 关于^: 匹配输入的开始。如果多行标志被设置为 true,那么也匹配换行符后紧跟的位置。
// 例如,/^A/ 并不会匹配 "an A" 中的 'A',但是会匹配 "An E" 中的 'A'。
参考:正则表达式系列总结 - 知乎