熟悉js正则,让你使用正则不再上网查

185 阅读4分钟

导言

开发中会遇到很多的正则使用场景,特别是表单验证的时候,或是在阅读前辈的代码的时候(如果没有注释,读起来比写起来更艰难),而大部分的开发者写正则的机会很少,一般都是用一些公共类型做验证,但是这无法满足个性化的验证,所以熟悉正则,能够为大家节约很多的发量。顺便安利一个工具,能够根据正则生成图形化的流程图 正则图形化工具

创建Regexp对象

  • 字面量。示例:
let reg = /\bis\b/g // g表示全局匹配 \b表示匹配一个零宽单词边界 这个正则表示匹配is这个单词
'you are beautiful,who are they'.replace(reg,'aaa') // "you aaa beautiful,who aaa they"
  • 构造函数。示例:
let reg = new RegExp('\\bit\\b','gi') // 字符串中使用反斜线需要转义
'It is a apple,what is it?'.replace(reg,'aaa')  // "aaa is a apple,what is aaa?"

常用修饰符

  • g: 全文搜索,不添加则搜索到第一个停止。
  • i: 是否忽略大小写,默认忽略,添加则不区分大小写。
  • m: 多行搜索,针对于换行的字符串。
  • 除此外还有u,y,s.可自行百度。

字符类型

  • 原义文本字符(1,2,3,a,b,c)
  • 元字符:有特殊含义的非字母字符(\t \n \b)文档
  • * + - $ ^ [ ] { } \ . ( )

字符类,范围类 and

[] 表示一个字符类,如[1-9][a-z]就分别表示数字1到9,和字母a到z

'1230'.replace(/[^1-9]/g,'a') // "123a" ^表示取反

常用的预定义类

字符 等价类 含义
. [^\r\n] 非回车符和换行符
\d [0-9] 数字
\D [^0-9] 非数字
\w [a-zA-Z_0-9] 单词字符(数字下划线)
\W [^a-zA-Z_0-9] 非单词字
\s 空白符
\S 非空白符

边界

  • \b 单词边界
This is an apple.replace(/\Bis\b/g,'0') // Th0 is an apple
  • ^ 在[]外表示开始
  • $ 在[]外表示结束
let a = '!123!qaz!'
a.replace(/^!./,':')
":23!qaz!"
a.replace(/.!$/,':')
"!123!qa:"

数量规则

字符 含义
0次或者1次,最多一次
+ 最少1次
* 任意次
{n} n次
{n,m} n到m次
{n,} 至少n次

贪婪模式和非贪婪模式

正则表达式会尽可能多的去匹配,这被称为贪婪模式 ,可以加?做非贪婪模式的匹配

'12345678'.replace(/\d{3,6}/g,0)
"078"
'12345678'.replace(/\d{3,6}?/g,0)
"0078"

分组

()可以将将字面量进行分组,作为一个整体来使用数量控制

'a1b2c3d4'.replace(/([a-z]\d){3}/g,'X')
"Xd4"
'applepenappleben'.replace(/apple(b|p)en/g,"0") // | 表示或匹配
"00"
//反向引用 分组取参 按分组顺序可以对应 $1 $2 $3...
'2020-05-20'.replace(/(\d{4})-(\d{2})-(\d{2})/g,"$2/$3/$1")
"05/20/2020"

"bryent".replace(/(br)/,"_$1_")
"_br_yent"
"bryent".replace(/(?:br)/,"_$1_") // ?:表示只分组不捕获
"_$1_yent"

前瞻

正则表达式从文本头部向尾部开始解析,文本尾部方向,称为“前”;前瞻就是在正则表达式匹配到规则的时候,向前检查是否符合断言

  • 正向前瞻:excp(?=assert)
  • 负向前瞻(非的意思):excp(?!assert)
'a8*34vv'.replace( /\w(?=\d)/g , 'X') // 表示匹配的是后面跟着的值是数字的 单词字符
"X8*X4vv"
'a8*34vv'.replace( /\w(?!\d)/g , 'X')  // 表示匹配的是后面跟着的值不是数字的 单词字符
"aX*3XXX"

对象属性

  • global: 是否全文搜索,默认false
  • ignoreCase: 是否大小写敏感,默认false
  • multiline: 是否多行搜索,默认false
  • lastIndex:是当前表达式匹配内容的最后一个字符的下一个位置
  • source: 正则表达式的文本字符串

对象方法

  • test方法:用于检测字符串是否符合规则,返回一个布尔值。如正则表达式设置了全局匹配,此方法的执行会改变原正则表达式的lastIndex属性,再次执行时会通过lastIndex开始匹配;
// 同一个正则对象全局执行多次可能会得到我们并不想要的结果,这个情况可以去掉全局匹配,或者每次匹配的时候新建一个正则对象 如:/foo/g.test('foo')
var regex = /foo/g;
// regex.lastIndex is at 0
regex.test('foo'); // true  

// regex.lastIndex is now at 3
regex.test('foo'); // false
  • exec方法:在一个指定字符串中执行一个搜索匹配。返回一个结果数组或 null。同test方法,在设置了 global 或 sticky 标志位的情况下(如 /foo/g or /foo/y),JavaScript RegExp 对象是有状态的。他们会将上次成功匹配后的位置记录在 lastIndex 属性中。
let reg1= /\bfoot\d\b/g
reg1.exec('foot1 and footer and football,foot2')
// ["foot1", index: 0, input: "foot1 and footer and football,foot2", groups: undefined]
reg1.exec('foot1 and footer and football,foot2')
// ["foot2", index: 30, input: "foot1 and footer and football,foot2", groups: undefined]

let reg2= /\bfoot(\d)\b/g // 包含分组时
reg2.exec('foot1 and footer and football,foot2')
 // ["foot1", "1", index: 0, input: "foot1 and footer and football,foot2", groups: undefined]
reg2.exec('foot1 and footer and football,foot2')
// ["foot2", "2", index: 30, input: "foot1 and footer and football,foot2", groups: undefined]

字符串方法

  • search 如果匹配成功,则 search() 返回正则表达式在字符串中首次匹配项的索引;否则,返回 -1
var str = "hey JudE";
var re = /[A-Z]/g;
console.log(str.search(re)); // 4
  • match 正则表达式不包含 g 标志,str.match() 将返回与 RegExp.exec(). 相同的结果。
var str = 'For more information, see Chapter 3.4.5.1';
var reg = /see (chapter \d+(\.\d)*)/ig;
str.match(reg); // ["see Chapter 3.4.5.1"]

// 不包含g
var re = /see (chapter \d+(\.\d)*)/i;
str.match(re);// ["see Chapter 3.4.5.1", "Chapter 3.4.5.1", ".1", index: 22, input: "For more information, see Chapter 3.4.5.1", groups: undefined]

  • replace 第一个参数是正则,第二个参数是目标值。目标值可以是普通字面量,也可以说正则分组值$1,$2。还可以是一个回调,回调有四个参数,分别是 匹配的值,分组值(如有),索引,原字符串
'a1b2c3'.replace(/\d/g,function(match,index,source){
    return parseInt(match+1)
})
//  a2b3c4

'a1b2c3d4e5'.replace(/(\d)(\w)(\d)/g,function(match,group1,group2,group3,index,source){
    return group1+group3
})
// a12c34e5