前端正则表达式基本语法

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

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

1. RegExp对象


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

  • 使用字面量实例化
    var reg = /\bis\b/
    'He is a boy. This is a dogis.'.replace(reg,'IS')
    //He IS a boy. This is a dogis.
    var reg = /\bis\b/g
    'He is a boy. This is a dogis.'.replace(reg,'IS')
    //He IS a boy. This IS a dogis.
    
  • 使用构造函数实例化
    //使用构造函数实例化
    var reg = new RegExp('\\bis\\b','g')
    'He is a boy. This is a dogis.'.replace(reg,'IS')
    //He IS a boy. This IS a dogis.
    var reg = /\bis\b/gi
    'He Is a boy. This Is a dogis.'.replace(reg,'0')
    //He 0 a boy. This 0 a dogis.
    

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

符号 解释 默认值
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)

  • 返回数组
  • 第一个元素是与正则表示相匹配的文本
  • 第二个元素是与RegExpObject的第一个子表达式相匹配的文本(如果有的话)
  • 第三个元素是与RegExp对象的第二个子表达式相匹配的文本(如果有的话),以此类推
  • 子表达式就是分组的内容
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)

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

  • 方法返回第一个匹配结果的index,搜索不到返回-1
  • search()方法不执行全局匹配,忽略标志g,并且总是从字符串的开始进行
  • search参数不是正则的都会尝试转换成正则
'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的引用
  • 若是非全局调用的话(无g),是和正则表达式方法的exec用途相反
  • 若是全局调用,match只是返回数组,不会有index什么的
    例子:
String.prototype.split(reg)
'a,b,c,d'.split(',')
'a1b2c3d4e'.split(/\d/g)
// ["a", "b", "c", "d", "e"]
12.3 String.prototype.replace

三个用法:

  • String.prototype.replace(str, replaceStr)
  • String.prototype.replace(reg, replaceStr)
  • String.prototype.replace(reg, function(){})

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

  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"
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345