正则表达式
regular expression
一个有规则的表达式
简单的说 他就是一个用于 查找的通配符
1 | book |
b*k 或 b?k
将以 b 开头, 以 k 结尾的单词 全部列出来
正则表达式就是 一个用于查找的 含有 匹配字符串 或 匹配元字符的 字符串
1 | “123” |
正则表达式对象
js 正则表达式对象 就是 由 正则表达式创建的对象, 该对象可以进行 匹配, 提取 和 替换.
创建正则表达式对象
构造函数
var regex = new RegExp( 正则表达式字符串[, 匹配模式] );
字面量
var regex = /正则表达式/;
使用正则表达式进行匹配
语法:
正则对象.test( 字符串 ) -> bool
如果参数字符串中含有 复合 正则匹配的 子字符串, 就返回 true, 否则返回 false
例如: 查询一段文字中是否包含 itcast
基本元字符
. 表示任一个非换行的字符
案例: foot _ 是 food, foot 写成 foo.
() 表示分组和提高优先级
[] 表示一个字符, 出现在 [] 中的字符
用法: [abc] 出现 [] 中的任意一个字符
匹配 a, 或 b, 或 c
1 | foo[dt] |
| 或
用法: 正则表达式|正则表达式
1 | foot 或 food |
扩展:
. 任意的一个字符. 没有任何限制
[] 是出现在[]中的一个字符. 认为 . 的限制级版本
[abc]: a 或者 b 或者 c
| 可以认为是 允许使用多个字符的 匹配
1 | a|b|c |
转义字符:
表示点: .
表示[]: [ ]
表示(): ( )
表示\ : \
限定元字符
紧跟前面的一个字符或一组字符出现 0 次到多次
表示: 123333333 后面很多 3
正则: 1233
123 0 次
1233 1 次
12333 2 次
…
1233333333333333333
1(23)*
表示:
1 0 次
123 1 次
12323 2 次
1232323 3 次
+ 紧跟在前面的字符出现 1 次到多次
字符串: 123333333
正则: 123+
123
1233
12333
? 紧跟在前面的字符出现 0 次或 1 次
在一段字符串中检查是否含有 http 协议的字符串或 https 协议的字符串
http://.+|https://.+
https?://.+
{数字} 紧跟在前面的字符出现指定次数
1 | a{3} aaa |
{数字,} 紧跟在前面的字符至少出现指定次数
1 | a{3,} aaa, aaaaaaaaa, aaaaaaaaaaaaaa, … |
{数字, 数字} 紧跟在前面的字符出现的次数范围
1 | a{1, 3} a, aa, aaa |
首尾正则表达式
^ 表示必须以 xxx 开头
^a 必须以 a 开头的字符串
a 表示一个字符串中只要含有 a 就可以匹配
^a^a 非法的写法, ^ 如果是表示开头必须写在开头, 而且只能写一个
表示必须以xxx结尾a 必须以 a 结尾
分析 ^a+$
案例
写一个正则表达式匹配 身份证号码
身份证是 18 位数字
省 市 区 出生年月 随机编码X
- 首先是要做匹配, 就一定要使用 ^ $
- 是 18 位数字( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ). 可以使用 [0123456789]
还可以使用 0|1|2|3|4|5|6|7|8|9 - 要求是 18 位. 限定 18 位, 即 {18}
组合: ^[0123456789]{18}$
如果最后一位是x
前面 17 位数字: ^[0123456789]{17}$
后面要么是数字: [0123456789]
要么是 x: x
写法: [0123456789x]
[0123456789]|x
0|1|2|3|4|5|6|7|8|9|x
^[0123456789]{17}[0123456789x]$
匹配邮箱
12345678901@qq.com
abcdefg@126.com
abcdefg@163.com
abc@yahoo.com.cn
.cc
.org
.edu
.中文
…
名字 @ 主机名
是要验证邮箱, 那么就需要使用 ^ $
名字:
数字与字母
[0123456789]
[abcdefghi…]
[ABCDEFG…][] 里面的字符如果是编码序号连续的可以使用连字符连接
数字: [0-9][9-0] 错误的, 编码逆序字母: [a-z]
[A-Z]整合: [0-9a-zA-Z]
名字的变式方法: [0-9a-zA-Z]+
主机名
主机名也是一串字符串或数字
但是它多了一个 .com .cn
3.1) 只有名字 [0-9a-zA-Z]+
3.2) 只含有一个 .什么
开始 .
中间 [0-9a-zA-Z]+
只含有一个名字: .[0-9a-zA-Z]+
3.3) 含有多个名字
.com.con.cc.c1.c2.c3
即 .什么 出现一次到多次
1 | (\.[0-9a-zA-Z]+)+ |
最后主机名可以写成
1 | [0-9a-zA-Z]+(\.[0-9a-zA-Z]+)+ |
最后整合一下
1 | ^[0-9a-zA-Z]+@[0-9a-zA-Z]+(.[0-9a-zA-Z]+)+$ |
匹配一个数字
匹配一个数字
[0-9]+
- 由于是匹配, 包含 ^ 2)首先第一个字符不允许是0,所以第一个可以写成[1−9]3)后面的数字就是[0−9]4)要求后面的数字出现0次到多次,以匹配任意的非0数字:[1−9][0−9]5)由于还需要考虑0,因此写成[1−9][0−9]|06)考虑|优先级最低:([1−9][0−9]∗|0)
^(-?[1-9][0-9]*|0)$
2> 匹配一个指定范围的数字
匹配 0 ~ 255 为例
[0-255] 0, 1, 2, 5 错误的
如果要匹配指定范围的数字, 那么需要将字符串结构进行分类
- 0 要匹配的, 所以在正则表达式中有 0 这一项
- 任意的 2 位数, 即 [1-9][0-9]
- 任意的 1 位数, 即 [0-9], 可以将 第 1) 结论合并
- 考虑 3 位数的时候, 只允许出现 1xx 的任意数, 而 2xx 的有限制
因此在分组, 考虑 1xx 的任意数, 可以写成: 1[0-9][0-9] - 考虑 2xx 的数字, 在 200 到 250 之间允许任意取. 所以
写成: 2[0-4][0-9] - 考虑 250 到 255, 写成 25[0-5]
1
2
3
4
5
6
7综合一起:
^([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$
匹配赢 IPv4
127.0.0.1
192.168.1.1
^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]))$匹配小数
要求, 小数不允许以 0 结尾jq 中有一属性过滤选择器1
2
3
4
5
6
7
83.1415
[0-9]*[1-9]
^((-?[1-9][0-9]*|0)(\.[0-9]*[1-9])?)$
(aaa)? 这个内容出现或不出现
(aaa|) 也是表达aaa可出现可不出现
^((-?[1-9][0-9]*|0)(\.[0-9]*[1-9]|))$了解1
[value=name] [value] [value !=name] ...
1
\[[a-zA-Z]((!|\||~|^|$|)=...|)\]
简写元字符
js 中常常使用 [\s\S] 表示任意字符1
2\s 空白字符, 包括空格, tab, 回车换行等
\S 非空白字符1
2
3
4
5\w 表示字符, 包含字母, 数字, 下划线.
\W 非字符
\d 数字
\D 非数字提取
使用正则表达式可以进行匹配, 使用 exec 可以将匹配到的数据提取出来
语法:
1 | 正则表达式对象.exec( 字符串 ) -> 封装成数组 |
案例: 在 ‘abc123def456ghij789klum’ 提取数字
循环提取
在一个字符串中将所有复合的要求的字符串提取出来
正则表达式需要使用全局模式
1 | var r = new RegExp( ‘正则’, ‘g’ ); |
调用 exec 首先获得第一个匹配项
再调用一次该方法, 就可以获得 第二个匹配项
一直调用下去, 就可以得到所有的匹配项
直到最后全部匹配完, 如果还用该方法, 则返回 null
案例: 在 ‘abc123def456ghij789klum’ 提取数字
1 | var r = /\d+/g; |
将匹配到的结果进行解析
假如有一个字符串: itcast@itcast.cn
匹配提取邮箱, 同时将邮箱地址部分的名字和主机名都提取出来
案例:
var str = ‘我有一个邮箱, 是 itcast@itcast.cn, 还有 abc@126.com, 和 1234567@qq.com‘
要求将里面的邮箱全部提取出来, 然后将名字还有主机名也取出来
1 | // 循环提取的正则表达式 |
匹配但是不去捕获的元字符
1 | (?:其他正则表达式内容) |
要截取一个字符串中的一个 html 标签
var str = ‘1234567890’;
要截取 html 标签, 标签使用 <>. 因此正则表达式写成 <\w+>
与之匹配的标签名是什么?
如果在一个正则表达式中使用组匹配到某一个数据, 允许在该正则表达式中使用
‘\数字’ 的方式引用该组
1 | <(\w+)>.*<\/\1> |
贪婪模式
凡是在正则表达式中, 涉及到次数限定的, 一般默认都是尽可能的多匹配.
取消贪婪模式. 在次数限定符后面加上 ?
注意: 贪婪模式性能会略高于非贪婪模式, 所以开发的时候. 一般不考虑贪婪的问题
只有代码匹配结果出现问题了, 一般一次多匹配了, 才会取消贪婪
多个贪婪在一起的时候的强度
1 | \d+\d+\d+ |
如果取消贪婪模式
1 | \d+?\d+\d+ |
否定元字符
语法:
[^字符]
不为这些字符的字符
[^abc] 不是 a 也不是 b 也不是 c 的字符
字符串的替换
语法:
1 | 字符串.replace( 查找字符串, 替换字符串 ) -> 字符串 |
字符串替换方法
1 | 字符串1.replace( 字符串2, 字符串3 ) |
在 字符串1 中找到 字符串2, 将其替换成 字符串3, 返回替换后的字符串
特点: 只替换第一个找到的字符串
1 | "aaa".replace( 'a', 'A' ) -> 'Aaa' |
正则替换
1 | 字符串.replace( 正则表达式, 字符串 ) -> 字符串 |
- 简单替换
1
2'aaaaa-------bbbbbb------ccccc'.replace( /-+/, '-' )
'aaaaa-------bbbbbb------ccccc'.replace( /-+/g, '-' ) - 分组替换
可以在替换字符串中, 使用 $数字 来引用替换的数据1
2
3
4
5
6
7
8'abc123'.replace( /(\d+)/, 'd$1' ) -> 'abcd123'
'1991-1-1'
中国: 1991年1月1日
欧洲: 1/1/1991
... : 1991 1 1
'1991-1-19'.replace( /(\d+)-(\d+)-(\d+)/, '$1年$2月$3日' )函数参数用法(了解)
语法:
字符串.replace( 正则表达式, fn )1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22'我的邮箱是:abc@itcast.cn, 你的邮箱是: defghijk@itcast.cn'
.replace( /\w+@\w+(\.\w+)+/g, '*' );
'我的邮箱是:abc@itcast.cn, 你的邮箱是: def@itcast.cn'
.replace( /(\w+)@(\w+(\.\w+)+)/g, function ( s, g1, g2, g3 ) {
return '*';
} );
// 要求 只显示 第一个字符, 其余的都是用 * 表示
'我的邮箱是:abc@itcast.cn, 你的邮箱是: defghijklim@itcast.cn'
.replace( /(\w+)@(\w+(\.\w+)+)/g, function ( s, g1, g2, g3 ) {
// 将用户名 变成 a***** 的形式
var first = g1.charAt( 0 );
var start = [];
for ( var i = 0; i < g1.length - 1; i++ ) {
start.push( '*' );
}
return first + start.join('') + '@' + g2;
} );