常用17个正则表达式整理

正则表达式

regular expression
一个有规则的表达式
简单的说 他就是一个用于 查找的通配符

1
2
3
4
book
bok
bouk

b*k 或 b?k

将以 b 开头, 以 k 结尾的单词 全部列出来
正则表达式就是 一个用于查找的 含有 匹配字符串 或 匹配元字符的 字符串

1
2
3
4
“123”
“abc”

“\d” 一个数字( 0 ~ 9 )

正则表达式对象

js 正则表达式对象 就是 由 正则表达式创建的对象, 该对象可以进行 匹配, 提取 和 替换.

创建正则表达式对象

构造函数

var regex = new RegExp( 正则表达式字符串[, 匹配模式] );

字面量

var regex = /正则表达式/;

使用正则表达式进行匹配

语法:

正则对象.test( 字符串 ) -> bool
如果参数字符串中含有 复合 正则匹配的 子字符串, 就返回 true, 否则返回 false

例如: 查询一段文字中是否包含 itcast

基本元字符

. 表示任一个非换行的字符

案例: foot _ 是 food, foot 写成 foo.

() 表示分组和提高优先级

[] 表示一个字符, 出现在 [] 中的字符

用法: [abc] 出现 [] 中的任意一个字符
匹配 a, 或 b, 或 c

1
foo[dt]

| 或

用法: 正则表达式|正则表达式

1
2
3
foot 或 food
foot|food
foo(t|d)

扩展:
. 任意的一个字符. 没有任何限制
[] 是出现在[]中的一个字符. 认为 . 的限制级版本
[abc]: a 或者 b 或者 c
| 可以认为是 允许使用多个字符的 匹配

1
2
a|b|c
aa|bb|cc

转义字符:
表示点: .
表示[]: [ ]
表示(): ( )
表示\ : \

限定元字符

紧跟前面的一个字符或一组字符出现 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

  1. 首先是要做匹配, 就一定要使用 ^ $
  2. 是 18 位数字( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ). 可以使用 [0123456789]
    还可以使用 0|1|2|3|4|5|6|7|8|9
  3. 要求是 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
.中文

名字 @ 主机名

  1. 是要验证邮箱, 那么就需要使用 ^ $

  2. 名字:
    数字与字母
    [0123456789]
    [abcdefghi…]
    [ABCDEFG…]

    [] 里面的字符如果是编码序号连续的可以使用连字符连接
    数字: [0-9]

       [9-0] 错误的, 编码逆序
    

    字母: [a-z]

       [A-Z]
    

    整合: [0-9a-zA-Z]

    名字的变式方法: [0-9a-zA-Z]+

  3. 主机名
    主机名也是一串字符串或数字
    但是它多了一个 .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]+

  1. 由于是匹配, 包含 ^ 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 错误的

如果要匹配指定范围的数字, 那么需要将字符串结构进行分类

  1. 0 要匹配的, 所以在正则表达式中有 0 这一项
  2. 任意的 2 位数, 即 [1-9][0-9]
  3. 任意的 1 位数, 即 [0-9], 可以将 第 1) 结论合并
  4. 考虑 3 位数的时候, 只允许出现 1xx 的任意数, 而 2xx 的有限制
    因此在分组, 考虑 1xx 的任意数, 可以写成: 1[0-9][0-9]
  5. 考虑 2xx 的数字, 在 200 到 250 之间允许任意取. 所以
    写成: 2[0-4][0-9]
  6. 考虑 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 结尾
    1
    2
    3
    4
    5
    6
    7
    8
    3.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]|))$
    jq 中有一属性过滤选择器
    1
    [value=name] [value] [value !=name] ...
    了解
    1
    \[[a-zA-Z]((!|\||~|^|$|)=...|)\]

    简写元字符

    1
    2
    \s 空白字符, 包括空格, tab, 回车换行等
    \S 非空白字符
    js 中常常使用 [\s\S] 表示任意字符
    1
    2
    3
    4
    5
    \w 表示字符, 包含字母, 数字, 下划线.
    \W 非字符

    \d 数字
    \D 非数字

    提取

    使用正则表达式可以进行匹配, 使用 exec 可以将匹配到的数据提取出来

语法:

1
正则表达式对象.exec( 字符串 ) -> 封装成数组

案例: 在 ‘abc123def456ghij789klum’ 提取数字

循环提取

在一个字符串中将所有复合的要求的字符串提取出来

正则表达式需要使用全局模式

1
2
var r = new RegExp( ‘正则’, ‘g’ );
var r = /正则/g;

调用 exec 首先获得第一个匹配项

再调用一次该方法, 就可以获得 第二个匹配项
一直调用下去, 就可以得到所有的匹配项
直到最后全部匹配完, 如果还用该方法, 则返回 null

案例: 在 ‘abc123def456ghij789klum’ 提取数字

1
2
3
4
5
6
7
8
9
10
var r = /\d+/g;

r.exec( str ) => 123
r.exec( str ) => 456
r.exec( str ) => 789
r.exec( str ) => null

while ( res = r.exec( str ) ) {
// 操作 res, 处理捕获的结果
}

将匹配到的结果进行解析

假如有一个字符串: itcast@itcast.cn

匹配提取邮箱, 同时将邮箱地址部分的名字和主机名都提取出来

案例:
var str = ‘我有一个邮箱, 是 itcast@itcast.cn, 还有 abc@126.com, 和 1234567@qq.com
要求将里面的邮箱全部提取出来, 然后将名字还有主机名也取出来

1
2
3
4
5
6
7
8
9
// 循环提取的正则表达式
var r = /[a-zA-Z\d]+@[a-zA-Z\d]+(.[a-zA-Z\d]+)+/g;

// 如果需要将匹配到的结果再次分解, 可以使用分组的形式, 在正则中分组即可

var r = /([a-zA-Z\d]+)@([a-zA-Z\d]+(.[a-zA-Z\d]+)+)/g;

// 注意, 正则表达式中, 分组是有编号的. 从左往右数 ‘(‘. 从 1 开始依次编号
// 匹配提取的结果中, 对应的编号就可以获得分解的数据

匹配但是不去捕获的元字符

1
(?:其他正则表达式内容)

要截取一个字符串中的一个 html 标签

var str = ‘1234567890’;

要截取 html 标签, 标签使用 <>. 因此正则表达式写成 <\w+>

与之匹配的标签名是什么?

如果在一个正则表达式中使用组匹配到某一个数据, 允许在该正则表达式中使用
‘\数字’ 的方式引用该组

1
<(\w+)>.*<\/\1>

贪婪模式

凡是在正则表达式中, 涉及到次数限定的, 一般默认都是尽可能的多匹配.

取消贪婪模式. 在次数限定符后面加上 ?

注意: 贪婪模式性能会略高于非贪婪模式, 所以开发的时候. 一般不考虑贪婪的问题
只有代码匹配结果出现问题了, 一般一次多匹配了, 才会取消贪婪

多个贪婪在一起的时候的强度

1
2
3
\d+\d+\d+

1234567

如果取消贪婪模式

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. 简单替换
    1
    2
    'aaaaa-------bbbbbb------ccccc'.replace( /-+/, '-' )
    'aaaaa-------bbbbbb------ccccc'.replace( /-+/g, '-' )
  2. 分组替换
    可以在替换字符串中, 使用 $数字 来引用替换的数据
    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;

    } );