0%

正则表达式学习笔记

JavaScript 正则表达式

字符匹配

横向模糊匹配

一个正则可匹配的字符串的长度不是固定的,可以用量词加以限制。

例如:{m,n}表示至少连续出现m次,最多出现n次。

1
2
3
4
var regex = /ab{2,3}c/g;    //这里g是正则的一个修饰符,表示全局匹配,global
表示第一个字符是a,接下来是23个b,最后是c
var string = "abc abbc abbbc abbbc abbbbbc";
console.log(string.match(regex));

image-20220110160440143

纵向模糊匹配

列出多种可能选择,比如[abc],可以是字符a、b、c任意一个。

1
2
3
var regex = /a[123]b/g;
var string = "a0b a1b a2b a3b a4b";
console.log(string.match(regex));

image-20220110160754823

修饰符
修饰符 描述
i 执行对大小写不敏感的匹配
g 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)
m 执行多行匹配w
字符组

字符组就是给出一组字符,判断是否含有。

  1. 范围表示法:用连字符“-“来表示。例如:[1-6] 匹配1~6中数字

如果要匹配的就是”-“,需要在前面加个转义字符”/“

  1. 排除字符组:反向寻找,求反,求补集意思,用脱字符”^"表示。例如:[^abc] 表示除了abc之外的任意字符
字符组 具体含义
[0-9],digit数字
1,除了0~9
[0-9a-zA-Z_],word单词字符
2
[ 空格,水平制表符,垂直制表符,换行符,回车符
3
. 表示任意字符
量词
量词 具体含义
{m,} 至少出现m次
{m} 等价于{m,m} 出现m次
等价于{0,1}出现一次或者不出现
+ 等价于{1,},至少出现一次
* 等价于{0,},出现任意次,可能不出现L
贪婪匹配 惰性匹配

尽可能匹配的多;尽可能匹配的少

1
2
3
4
5
var regex = /\d{2,3}/g;
var regex1 = /\d{2,3}?/g;
var string = "12 123 1234 12345";
console.log(string.match(regex));
console.log(string.match(regex1));

image-20220111101935196

惰性量词,上述表格的量词也是贪婪量词,惰性量词就是在其后加个?

多选分支

用管道符“|”分隔,表示其中任意之一,类似或者。例如:匹配super,hero字符

/super|hero/

匹配十六进制颜色值

表示一个十六进制字符,可以用[0-9a-fA-F]表示,其中字符可以出现3或6次,所以需要用到量词和分支结构

1
2
3
4
var regex = /#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})/g;
//这里需要注意一下顺序,由于分支匹配是惰性的,如果先将3放前面,可能原本是6字符的颜色就只取了一部分导致错误,所以应该先将6放前面。
var s = "#ffbbad #Fc01DF #FFF #ffE";
console.log(s.match(regex));

image-20220111103502386

匹配时间

匹配一个24小时制的时间,要求匹配:23:59 02:07

1
2
3
var regex = /([01][0-9]:[0-5][0-9])|(2[0-3]:[0-5][0-9])/g;
var regex1 = /^([01][0-9]|[2][0-3]):[0-5][0-9]$/;
// ^和$表示字符串的开头和结尾
匹配日期

比如yyyy-mm-dd

1
2
3
var regex = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/;
console.log(regex.test("2022-01-11"));
//true
匹配id
1
2
3
4
var regex = /id="[^"]*"/;
var s = '<div id="container" class="main"></div>';
console.log(s.match(regex)[0]);
//id="container"

位置匹配

位置(锚)是相邻字符之间的位置。

脱字符^ 美元符号$

^ 表示匹配行中开头,\(表示匹配行中结尾,^\)就是代表那个位置了,可以用其它字符替换

1
2
3
var test = "hello".replace(/$/g,"-superhero");
console.log(test);
//hello-superhero

多行匹配模式m

1
2
3
4
5
6
var result = 'I\nlove\nSuperhero'.replace(/^/gm,'@');
console.log(result);
=>
@I
@love
@Superhero

,即,^之间的位置,$之间的位置

的简写,,即

1
2
var result = "[JS] James_11.html".replace(/\b/g,'@');
[@JS@] @James_11@.@html@

匹配空白字符:空格、制表符、断行等

(?=p) 和 (?!p)

(?=p) ,p前面的位置; (?!p),(?=p)的反面,即后面不是p

1
2
3
4
var result = "hello".replace(/(?=l)/g,'@')
he@l@lo
var result = "hello".replace(/(?!l)/g,'@')
@h@ell@o@
(?<=p) (?<!p)

第一个意思是,首先选择p的前面位置,然后定位到p的右边;第二个是第一个反面,即后面不是p然后对p后面一个位置操作

1
2
var result = "hello".replace(/(?<=e)/g,'@')
he@llo
数字千位分隔符表示法
1
2
var result = "12345678".replace(/(?=\d{3}$)/g,',')
12345,678

$ 匹配最后3位数字前面的位置,如何弄出所以逗号呢?

1
2
3
4
var result = "12345678".replace(/(?=(\d{3})+$)/g,',')
12,345,678
// 表示从结尾向前数,三个数字后。就将其前面的位置替换成逗号
// 所以当123456789 就出现问题了 ,123,456,789

复习量词+ ,我们知道 /a+/ 匹配连续出现的a

1
2
var result = "123456789".replace(/(?!^)(?=(\d{3})+$)/g,',')
// 123,456,789

验证密码问题

1
2
3
4
5
var regex = /(?=.*[0-9]^[0-9A-Za-z]{6,12}$/);
.*表示除了换行符的任意字符至少一个
var regex = /(?=.*[0-9])(?=.*[a-z])^[0-9A-Za-z]{6,12}$/;
同时包含数字和小写字母
var regex = /(?!^[0-9]{6,12}$)^[0-9A-Za-z]{6,12}$/;

分组匹配

用括号来对特定对象进行分组,从左至右第一个为第一组… 用$获取组的信息

1
2
3
4
[1]([0-9]).*([0-9])    默认前有/ 后有/g    
1235
$1 $2
2 5

分组匹配但不捕获

?:模式,匹配但不使用,即不占用$

例如匹配前四串数字的后四位

1
2
3
4
5
6
7
8
9
14915221000
12715223000
13915225000
13815229000

12315221000
13415221000
\1(49|27|38|39)\d{4}(\d{4}) 匹配前四串数字,使用了两个(),但第一个$1我们是不使用的,造成浪费,所以改用
\1(?:49|27|38|39)\d{4}(\d{4})

表达式括号

替换

yyyy-mm-dd 格式,替换成 mm/dd/yyyy 怎么做?

1
2
3
4
5
6
var regex = /(\d{4})-(\d{2})-(\d{2})/;
var string = "2017-06-12";
var result = string.replace(regex, function () {
return RegExp.$2 + "/" + RegExp.$3 + "/" + RegExp.$1;
});
console.log(result);

反向引用

匹配这三组2016-06-12 2016/06/12 2016.06.12

1
2
3
var regex = /\d{4}(-|\/|\.)\d{2}\1\d{2}/;
注意里面的 \1,表示的引用之前的那个分组 (-|\/|\.)。不管它匹配到什么(比如 -),\1 都匹配那个同
样的具体某个字符。

我们知道了 \1 的含义后,那么 \2 和 \3 的概念也就理解了,即分别指代第二个和第三个分组。 看到这里,为了更好理解,看一下下面这个

1
2
3
4
5
6
7
8
9
var regex = /^((\d)(\d(\d)))\1\2\3\4$/;
var string = "1231231233";
console.log( regex.test(string) ); // true
console.log( RegExp.$1 ); // 123
console.log( RegExp.$2 ); // 1
console.log( RegExp.$3 ); // 23
console.log( RegExp.$4 ); // 3
三个\d说明有三个数字 123-> 1 23, 23->2 3
对于括号嵌套,以左括号为准

\10是啥意思捏?

显然是第10个分组,如果真要匹配 \1 和 0 的话,请使用 (?:\1)0 或者 \1(?:0)。

字符串trim方法模拟

1
Superhero   
  1. 匹配前后的空格然后用空字符替换
1
^\s+|\s+$
  1. 匹配中间的字符串,将原始字符串换为它
1
^\s*(.*?)\s*$

正则表达式编程

匹配后进行,正则表达式的四种操作,验证、切分、提取、替换

验证

有没有匹配,是不是匹配上,判断是否的操作。

按所属对象划分

  1. search() match() 属于String对象
  2. test() exec() 属于RegExp对象

按功能划分

  1. search() test() 验证是否匹配
  2. match() exec() 提取匹配项
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//用match、search、test、exec,常用test    
var regex = /^(\d{4})\D(\d{2})\D(\d{2})$/;
var string = "2017-06-26";
console.log( regex.exec(string) );
--------------------------------------------
Array(4) [ "2017-06-26", "2017", "06", "26" ]
0: "2017-06-26"
1: "2017"
2: "06"
3: "26"
groups: undefined
index: 0

console.log(string.match(regex))
--------------------------------------------
Array(4) [ "2017-06-26", "2017", "06", "26" ]
0: "2017-06-26"
1: "2017"
2: "06"
3: "26"
groups: undefined
index: 0
input: "2017-06-26"
length: 4

console.log(string.search(regex))
--------------------------------------------
0

console.log(regex.test(string))
--------------------------------------------
true

切分

1
2
3
4
var regex = /,/;
var string = "html,css,javascript";
console.log( string.split(regex) );
// => ["html", "css", "javascript"]

提取

1
2
3
4
5
6
7
8
var regex = /^(\d{4})\D(\d{2})\D(\d{2})$/;
var string = "2017-06-26";
var date = [];
string.replace(regex, function (match, year, month, day) {
date.push(year, month, day);
});
console.log(date);
// => ["2017", "06", "26"]

替换

1
2
3
4
var string = "2017-06-26";
var today = new Date( string.replace(/-/g, "/") );
console.log( today );
// => Date Mon Jun 26 2017 00:00:00 GMT+0800 (中国标准时间)