正则表达式

前端正则表达式基本语法

2019-03-15  本文已影响6人  啧啧扬

正则表示式在线测试工具网站,并以图例的方式呈现正则表达式:regexper.com
本文章内容通过学习Samaritan89老师的网课而总结的知识点

  1. RegExp对象
  2. 元字符
  3. 字符类
  4. 范围类
  5. 预定义类及边界
  6. 量词
  7. 正则贪婪模式与非贪婪模式
  8. 分组
  9. 前瞻
  10. 正则表达式的对象属性
  11. 正则表达式对象方法
  12. 跟正则表达式非常相关的字符串对象方法

1. RegExp对象


实例化RegExp对象有一下两种方法

正则的修饰符有以下几种:

符号 解释 默认值
g global 全文搜索 fasle,默认搜索到第一个匹配停止
i ignore case 忽略大小写 false,默认大小写敏感
m multiple lines 多行搜索 false,默认不匹配多行

2. 元字符


正则表达式由两种基本字符类型组成:

  1. 原义wenbenzifu
  2. 元字符

元字符是在正则表达式中有特殊含义的非子母字符
常用的有:* + ? $ ^ . \ () {} [] ,这些在下文篇幅中一一讲述,以及以下常用字符:

字符 含义
\t 水平制表符
\v 垂直制表符
\n 换行符
\r 回车符
\0 空字符
\f 换页符

3. 字符类


类:指符合某些特性的对象,是个泛指
元字符[ ] 匹配某类字符
例子:

'a1b2c3d4'.replace(/[abc]/g,'X')
//X1X2X3d4

在类[]中,使用元字符^创建反向类/负向类,如下:

//表达式[^abc]表示不是字符a或b或c的内容
'a1b2c3d4'.replace(/[^abc]/g,'X')
//aXbXcXXX

4. 范围类


正则表达式提供的范围类,如
[a-z]来连接两个字符,表示从a到z的任意字符,此表达的是闭区间,包括a和z
例子:

'a1b2c3x4z9'.replace(/[a-z]/g,'P')
// P1P2P3P4P9

在[ ] 组成的类内部是可以连写的[a-zA-Z]

'Aa1Bb2c3x4z9ASDFQW'.replace(/[a-zA-Z]/g,'P')
//"PP1PP2P3P4P9PPPPPP"

匹配数字和横线,即再单加一个-

'2019-03-09'.replace(/[0-9-]/g,'P')
//PPPPPPPPPP

5. 预定义类及边界


5.1 预定义类

预定义类是为了匹配常见的的字符类

字符 等价类 含义
. [^\r\n] 除了回车符、换行符之外的所有字符
\d [0-9] 数字字符
\D [^0-9] 非数字字符
\s [\t\n\x0B\f\r] 空白符
\S [^\t\n\x0B\f\r] 非空白字符
\w [a-zA-Z_0-9] 单词字符(子母、数字、下划线)
\W [^-zA-Z_0-9] 非单词字符

例子:匹配 ab+数字+任意字符 的字符串
/ab\d./等价于 /ab[0-9][^\r\n]/

5.2边界匹配字符####

字符 含义
^ 以xxx开始
$ 以xxx结束
\b 单词边界
\B 非单词边界

单词边界和非单词边界例子:

'This is a boy'.replace(/is/g,'0')
//Th0 0 a boy
'This is a boy'.replace(/\bis\b/g,'0')
//This 0 a boy
'This is a boy'.replace(/\Bis\b/g,'0')
//Th0 is a boy

字符串的首尾匹配例子:

'@123@abc@'.replace(/@./g,'Q')
//Q23Qbc@
'@123@abc@'.replace(/^@./g,'Q')
// Q3@abc@
'@123@abc@'.replace(/.@/g,'Q')
// @12QabQ
'@123@abc@'.replace(/.@$/g,'Q')
//@123@abQ

多行字符串的每行首尾匹配例子

'@123\n@456\n@789'.replace(/^@\d/g,'X')
//X23\n@456\n@789
'@123\n@456\n@789'.replace(/^@\d/gm,'X')
//X23\nX56\nX89

6. 量词


例子:匹配一个连续出现5次数字的字符串
/\d\d\d\d\d/等价于/\d{20}/
量词字符如下

字符 含义
? 出现零次或一次(最多一次)
+ 出现一次或多次(最少一次)
* 出现零次或多次(任意次)
{n} 出现n次
{n,m} 出现n到m次
{n,} 最少出现n次

例子:

'12343432'.replace(/\d?/,'z')
// "z2343432"
'12343432'.replace(/\d+/,'z')
// "z"   为什么匹配所有的数组,而不是匹配一个?看下一篇幅讲述
'12343432'.replace(/\d*/,'z')
// "z"
'12343432'.replace(/\d{4}/,'z')
// "43432"
'12343432'.replace(/\d{4,7}/,'z')
// "z2"
'12343432'.replace(/\d{4,}/,'z')
// "z"

7. 正则贪婪模式与非贪婪模式


一般情况下,正则是默认尽可能的匹配,即贪婪模式,如下例子

'12345678'.replace(/\d{3,6}/,'z')
//z78

开启非贪婪模式的方法:在量词后面添加问号

'12345678'.replace(/\d{3,6}?/,'z')
//z45678
'12345678'.replace(/\d{3,6}?/g,'z')
//zz78

8. 分组


8.1分组 ()

使用场景:匹配字符串连续出现三次的场景
例如:/Byron{3}/只能匹配连续3次的n,单词不重复
所以可以使用 元字符() 达到分组的功能,使量词作用域分组

var reg = /(Byron){3}/
'a1b2c3d4'.replace(/[a-z]\d{3}/g,'X')
// "a1b2c3d4"
'a1b2c3d4'.replace(/([a-z]\d){3}/g,'X')
// "Xd4"
8.2 或 |

使用 元字符| 达到或的效果,而不需要分组

'ByronCasper'.replace(/Byron|Casper/g,'X')
// "XX"

也可以在分组中使用

'ByronsperByrCasper'.replace(/Byr(on|Ca)sper/g,'X')
// "XX"
8.3 反向引用

反向引用可以捕获分组内容,用$n(n表示第n个分组)表示,同时$&表示整个正则表达式匹配的内容.例子如下:

'2019-03-10'.replace(/(\d{4})-(\d{2})-(\d{2})/g,'$2/$3/$1')
// "03/10/2019"
'2019-03-10'.replace(/(\d{4})-(\d{2})-(\d{2})/g,'时间:$&')
//"时间:2019-03-10"
8.4 忽略分组

如不希望捕获某些分组,需在分组的前面加上?:,例子:

'Byron1ok'.replace(/(?:Byron).(ok)/,'$1')
// "ok"

9. 前瞻


而前瞻就是在正则表达式匹配到规则的时候,向检查是否符合断言。
的解释:从文本头部向尾部开始解析,文本尾部方向,称为‘前’。
后顾/后瞻方向与之方向相反,但是javascript不支持后顾
前瞻中的正则表达式称为断言,又分为肯定/正向匹配和否定/负向匹配

名称 正则 含义
正向前瞻 exp(?=assert) 匹配到exp后,其后面字符是否能匹配assert的正则
负向前瞻 exp(?!assert) 匹配到exp后,其后面字符是否不能匹配assert的正则

例子:

'a2*34vv'.replace(/\w(?=\d)/g, 'X')
 //X2*X4vv
 'a2*34vv'.replace(/\w(?!\d)/g, 'X')
//aX*3XXX

10. 正则表达式的对象属性


  1. global:是否全文搜索,默认为false
  2. ignore case:是否大小写敏感,默认是fasle
  3. multiline:多行搜索,默认值是false
  4. lastIndex:是当前表达式匹配内容的最后一个字符的下一个开始搜索的位置
  5. source:正则表达式的文本字符串
var reg1 = /\w/;
var reg2 = /\w/gim; 
reg1.global //false
reg2.multiline //true

11. 正则表达式对象方法


11.1 RegExp.prototype.test(str)

用于测试字符串参数重是否存在匹配正则表达式模式的字符串,如果存在则返回true,否则返回false
但此方法,会有以下bug

var reg1 = /\w/
var reg2 = /\w/g
reg1.test('a')//true

reg2.test('ab')//true
reg2.test('ab')//true
reg2.test('ab')//false
reg2.test('ab')//true
reg2.test('ab')//true
reg2.test('ab')//false

会有以上原因主要是因为lastIndex此属性
正则对象的test()执行后,其自身的lastIndex属性值+1,循环着
解决方法:

  1. 每次都实例化一个 (/\w/g).test('ab'),然而每次实例化一个对象需要内存开销的
  2. 使用exec方法
11.2 RegExp.prototype.exec(str)

用途:使用正则表达式模块对字符串执行搜索,并将更新全局RegExp对象的属性以反映匹配结果

如果没有匹配的文本则返回null,否则返回一个结果数组,数组有两个额外的属性

  1. index:生命匹配文本的第一个字符的位置
  2. input:存放被检索的字符串string

非全局调用(即没有修饰符g)

var ts = '1a2b3c4d5e'
var reg3 = /\d(\w)\d/
var ret = reg3.exec(ts)
console.log(reg3.lastIndex+' '+ret.index+' '+ret.toString())
//0 0 1a2,a
console.log(reg3.lastIndex+' '+ret.index+' '+ret.toString())
//0 0 1a2,a

对整个字符串进行搜索,能获得到具体的值:

var ts = '1a2b3c4d5e'
var reg4 = /\d(\w)\d/g, ret
while(ret = reg4.exec(ts)){
    console.log(reg4.lastIndex+' '+ret.index+' '+ret.toString())
}
//2 3 0 1a2,a
//2 7 4 3c4,c

12. 跟正则表达式非常相关的字符串对象方法


12.1 String.prototype.search(reg)

用途:检索与正则表达式相匹配的子字符串

'a1b2c3d1'.search('1')
//1
'a1b2c3d1'.search(/1/)
//1
'a1b2c3d1'.search(1)
//1
12.2 String.prototype.match(reg)

用途:match()检索字符串,返回匹配的结果数组,没有则null
有两个对象属性

  1. index:声明匹配文本的起始字符在字符串的位置
  2. input:声明对stringObject的引用
String.prototype.split(reg)
'a,b,c,d'.split(',')
'a1b2c3d4e'.split(/\d/g)
// ["a", "b", "c", "d", "e"]
12.3 String.prototype.replace

三个用法:

上面的回调函数在每次匹配替换的时候调用,有四个参数

  1. 匹配字符串
  2. 正则表达式分组内容,没有分组则没有该参数
  3. 匹配项在字符串中的index
  4. 原字符串
'a1b1c1'.replace('1',2)
//a2b1c1
'a1b1c1'.replace(/1/g,2)
//a2b2c2
// 需要实现的目标:'a1b2c3d4' => 'a2b3c4d5'
'a1b2c3d4'.replace(/\d/g,function(match, index, origin){
    console.log(index)
    return parseInt(match)+1
})
// 1
// 3
// 5
// 7
// "a2b3c4d5"

'a1b2c3d4'.replace(/(\d)(\w)(\d)/g,function(match, group1, group2,group3, index, origin){
    console.log(match)
    return group1+group3
})
//1b2
//3d4
//"a12c34"
上一篇 下一篇

猜你喜欢

热点阅读