20分钟带你弄懂正则表达式

479 阅读5分钟

这是我参与 8 月更文挑战的第 13 天,活动详情查看: 8月更文挑战

工作中,遇到表单验证条件需要编写正则表达式基本都是百度,没有去想、去急为什么要这么去写。一次机缘巧合别人问我这个验证条件为什么写,一时竟然回答不出。。。 终于促使我下定决心好好去研究一次正则的规则,下面就贴出几天研究后的成功,和诸君一起共勉。

模式

标志正则表达式英文释义
多行模式mmultiple of lines
忽略大小写iignore case, case-insensitive
全局模式gglobal
  • 如果不带g,正则过程中字符串从左到右匹配,找到第一个符合条件的即匹配成功;返回 如果带g,则字符串从左到右,找到每个符合条件的都记录下来,知道字符串结尾位置
  • /m 匹配换行符两端的潜在匹配影响正则中的^$符号。若存在换行\n并且有开始^或结束$符的情况下,和g一起使用实现全局匹配, 因为存在换行时默认会把换行符作为一个字符任务匹配字符串是个单行, g只匹配第一行,添加m之后实现多行,每个换行符之后就是开始
let str = `
superLian (231144)" +
     "super Lu (155445)`
-
str.match(/lu/) // null
str.match(/lu/i) 
// ["Lu", index: 35, input: "\nsuperLian (231144)\" +\n     \"super Lu (155445)", groups: undefined]

str.match(/super/) //["super", index: 1, input: "\nsuperLian (231144)\" +\n     \"super Lu (155445)", groups: undefined]
str.match(/super/g) // ["super", "super"]

str = 'abcggab\nabcoab'
str.match(/^abc/g) // ["abc"]
str.match(/^abc/gm) //["abc", "abc"]
str.match(/ab$/g) //["ab"] 
str.match(/ab$/gm) ["ab", "ab"]
'abcggab\nabco'.match(/ab$/g) //null
'abcgg\nabcoab'.match(/ab$/g) //["ab"] 

元字符

代码说明英文释义等效写法
.除换行符(\n)以外的任意字符[^\n]
\w字母或数字或下划线word[A-Za-z0-9_]
\W非单字字符[^A-Za-z0-9_]
\s任意的空白符space[\f\n\r\t\v]
\S匹配非空白字符[^\f\n\r\t\v]
\d数字digit[0-9]
\D非数字,除了除了[0-9][^0-9]

边界

代码说明英文释义等效写法
\b单词边界,单词的开始或结束boundary
\B非单词边界
字符串的开始
$字符串的结束

| ?= | 前面的位置| |(?=p),其中p是一个子模式,即p前面的位置| | ?! | 前面的位置| |(?!p)就是(?=p)的反面意思|

大写为取反\反义,如\d匹配数字,\D匹配非数字

重复

代码/语法说明重复次数
*重复零次或更多次{0,}>=0
+重复一次或更多次{1,}>=1
?重复零次或一次, {0,1}0 | 1
{n}重复n次 {n,n}n
{n,}重复n次或更多次>=n
{n,m}重复n到m次>=n, <=m

转义

匹配特殊字符本身时需要转义,共有以下几个:
* . ? + $ ^ [ ] ( ) { } | \ /
  • 其中 / 在字面量中需要转义,在构造函数中不需要,如下匹配一个斜杠 /
const reg = /\//
const reg = new RegExp('/')
  • 在字面量中带一个转义符 \ 的用构造函数写要带两个转义符 \\,如下匹配一个字符串 .
const reg = /\./
const reg = new RegExp('\\.')

字符组[]

说明
[]或逻辑,匹配中括号之间的任何字符,可用连字符-来省略和简写,^在中括号中有取反的意思
[^abc]查找一个任何不在方括号之间的字符,^在中括号中有取反的意思。
[a-z]小写字符中的任何一个字符,-在中括号中表示从..到..
  • /[-.(]/ 在符号中的连字符-放在第一位表示连字符本身,如果放在中间,表示"从..到..",比如[a-z]表示a-z
  • 如要匹配“a”、“-”、“z”这三者中任意一个字符,写成如下的方式:[-az][az-][a\-z]。即要么放在开头,要么放在结尾,要么转义。总之不会让引擎认为是范围表示法就行了
  • [.)] 括号中的特殊符号不需要转义,就表示其本身
  • [^ab] 括号中的^表示非,anythings except a and b
  • (a|b)也可表示选择,但是它有更强大的功能....

分组捕获()

  • 分组捕获,使用()进行数据分组,编号0代表整个匹配项,选择的分组从1号开始
  • 选择器可以使用$1\1,但是使用场景不同,``用在正则表达式自己身上
  • ?符号可以禁止贪婪属性,放在.*之后,表示一次匹配遇到重点就可以停止。否则将会一直向后匹配。

贪婪匹配和惰性匹配

* 和 + 限定符都是贪婪的,它们会尽可能多的匹配文字。在它们的后面加上一个 ? 就可以实现非贪婪或最小匹配。 量词后面加个问号?就变成懒惰匹配

//数字连续出现2到5次
var reg1 = /\d{2,5}/g; // 贪婪匹配
var reg2 = /\d{2,5}?/g; // 惰性匹配
var string = "1 12 123 1234 12345 123456 1234567"; 
console.log( string.match(reg1) ); //["12", "123", "1234", "12345", "12345", "12345", "67"]
console.log( string.match(reg2) );//["12", "12", "12", "34", "12", "34", "12", "34", "56", "12", "34", "56"]

js中正则API

reg.test()

判断是否包含,返回一个bool变量reg.match(str)

/abc/.test('Abc') // false

str.match()

返回你所匹配到的内容str.match(reg)

'aaaaa'.match(/a/g) // ["a", "a", "a", "a", "a"]

reg.exec()

这个方法可以实现匹配全局,并返回分组的结果reg.exec(str)

str.split

我们在用 split() 分割字符','的时候,split() 方法也是把',' 隐士转换成正则'/,/'的, search() 方法和 replace() 方法也是一样的。

var str = 'a,b,c,d';
var arr = str.split(',');
console.log(arr); //['a','b','c','d']

var str = 'a1b2c3d';
var arr = str.split(/\d/);
console.log(arr); //['a','b','c','d']

var str = 'a1b&c|d&e';
var arr = str.split(/[\d|&]/);
console.log(arr); //['a','b','c','d','e']

str.replace()

String.prototype.replace(reg,function);中 function 的参数含义,function 会在每次匹配替换的时候调用,有四个参数(第二个参数不固定):

  1. 匹配字符串
  2. 正则表达式的分组内容,没有分组则没有该参数、
  3. 匹配项在字符串中的 index
  4. 原字符串
var str = 'a1b2c3d4e5';
var reg = /\d/g;
var arr = str.replace(reg,function(match, index, origin){
  console.log(index);// 1 3 5 7 9
  return parseInt(match) + 1;
})
console.log(arr);//a2b3c4d5e6 把每次匹配到的结果+1替换


var str = 'a1b2c3d4e5';
var reg = /(\d)(\w)(\d)/g;
var arr = str.replace(reg,function(match, group1, group2, group3, index, origin){
  console.log(match);// 1b2   3d4
  return group1 + group3;
})
console.log(arr);//a12c34e5  去除了每次匹配到的group2