详解js正则表达式

431 阅读18分钟

正则表达式是前端经常会经常使用到的知识,尤其是在对用户输入内容的校验中使用得非常多,虽然有些时候,使用函数和js方法操作字符串也能起到校验的目的,但是没有使用正则表达式的代码简洁易懂。而且使用正则表达式还可以实现很多强大的功能。

创建正则

创建正则有两种方式:字面量和对象的方式

1. 字面量

字面量很好理解就是直接定义一个正则字符串,像下面这样

let reg = /\d+/;
console.log(reg.test('你是谁。我是1'));  // true
console.log(reg.test('你是谁。我是未知数'));  // false

上述正则表达式中是用来检验字符串中是否存在数字,如果存在就返回true, 如果不存在就返回false。因此你可以看到上述打印结果。

2. RegExp对象

上面的例子也可以使用RegExp对象来创建正则。

let reg = new RegExp('\\d+');
console.log(reg.test('你是谁。我是1'));  // true
console.log(reg.test('你是谁。我是未知数'));  // false

3. 二者的区别

虽然字面量和RegExp对象的方式都可以创建正则表达式,但是它们在使用上还是有很一些区别的,主要有以下两点:

3.1 当正则中含有变量时

如果采用字面量校验

let aVal = 'a';
let reg = /aVal/;
console.log(reg.test('你是谁。我是a'));   // false

上述正则表达式是用来检验字符串是否变量aVal,也就是是否含有'a'。预期打印结果应该是true, 实际上打印出来的结果是fase. 原因很简单,就是字面量创建的正则表达式中的变量是不能被读取的,我们可以使用eval将变量解析出来,如下:

let aVal = 'a';
let reg = eval(`/${aVal}/`);
console.log(reg.test('你是谁。我是a'));   // true

这样的话就相当于是eval(`/${aVal}/`)会被解析成/a/,因此就会打印出true。

如果采用RegExp对象

let aVal = 'a';
let reg = new RegExp(aVal);
console.log(reg.test('你是谁。我是a'));   // true

当采用RegExp对象定义含有变量的正则表达式时,就可以直接被解析出来

小结

如果正则表达式中含有变量的时候,建议还是使用RegExp对象的方式来定义。

3.2 当正则中含有常规字符的内容时

当正则表达式中含有常规字符的内容时,字面量和RegExp对象的方式也是有一些区别的。

使用字面量的方式

let reg = /\W+/;
console.log(reg.test('我是谁?')); // true

当我们使用字面量创建时,只需要使用//包裹,然后在里面写常规字符即可。

使用RegExp对象

let reg = new RegExp('\W+');
console.log(reg.test('我是谁?')); 

当我们使用RegExp对象来创建的时候,是不需要使用//包裹,但是像上面这种写法打印结果是false。 当使用构造函数创造正则对象时,需要常规的字符转义规则(在前面加反斜杠 \)。

let reg = new RegExp('\\W+');
console.log(reg.test('我是谁?'));   //true

小结

对于字面量中使用正则表达式很简单,对于这种常规字符是不需要转义的,如果在使用RegExp中不确定自己是否需要转义或者转义是否正确,有一个很简单的方法就是将你的正则表达式字符串打印出来,如果是一个正确的正则表达式,那么就是转义正确的。

console.log('\d+\w');   // d+w
console.log('\\d+\\w');  // \d+\w

另说一点:在正则表达式中,任何字符如果在正则中有别的含义,那么在使用的时候一定要注意转义!!!

正则里面的字符

正则表达式里面是由很多字符组成的,根据它们的功能一共分为以下几类

  • 选择符
  • 边界符
  • 模式修饰符
  • 元字符
  • 量词
  • 组和范围

选择符

选择符用|表示,用来表示选择符左右两边有一个匹配到即可。相当于js逻辑运算中的或运算('||')。

let reg = /abc|ABC/;

上面的正则表达式用来匹配大小写的abc。

边界符

边界符是用来定义匹配内容的开始和结束约束。

  • ^: 匹配字符串的开始
  • $: 匹配字符串的结束,忽略换行符
let reg = /abc/;
console.log(reg.test('123abc344'));   // true

如果只是想要校验是否以abc开头

let reg = /^abc/;
console.log(reg.test('123abc344'));   // false
console.log(reg.test('abc344'));   // true

如果只是想要检验是否以abc结尾

let reg = /abc$/;
console.log(reg.test('123abc344'));   // false
console.log(reg.test('abc344'));   // false
console.log(reg.test('123abc'));   // true

模式修饰符

正则表达式在执行时会按照它的默认方式执行,有时候我们需要修改它的这种默认方式,那么就可以使用模式修饰符。因为模式修饰符可以改变正则表达式的默认执行方式。 模式修饰符一共有下面这几种:

  • i: 不区分大小写
  • g: 全局搜索匹配所有内容
  • m: 视为多行
  • s: 视为单行,忽略换行符
  • y: 从RegExp.lastIndex开始匹配

i修饰符

在正则表达式中,默认是按照你所写的字符的大小写来进行匹配校验的,如果你不想区分大小写的话,那么就可以使用i模式修饰符。

let reg = /abc/;
console.log(reg.test('aBc'));  // false

加上i修饰符

let reg = /abc/i;
console.log(reg.test('aBc'));  // true

g修饰符

在正则表达式中,默认是查找到了符合正则表达式的字符之后就不会继续往下查找,但是如果你想要继续查找,查找出全局符合条件的字符,那么就可以使用g这个修饰符。

let reg = /abc/;
console.log('abcdefgfeabc'.replace(reg, '@'));    // @defgfeabc
console.log('abcdefgfeabc'.match(reg));  // ['abc', index: 0, input: 'abcdefgfeabc', groups: undefined]

加上g修饰符

let reg = /abc/g;
console.log('abcdefgfeabc'.replace(reg, '@'));  // @defgfe@
console.log('abcdefgfeabc'.match(reg));  // ['abc', 'abc']

m修饰符

正则表达式默认解析是按照单行来进行匹配校验的的,但是如果想要按照多行来进行匹配校验,需要使用m模式修饰符。

let reg = /^abc/;
let str = '24233\ndef345\nabc567';
console.log(str.match(reg));   // null

使用m修饰符

let reg = /^abc/m;
let str = '24233\ndef345\nabc567';
console.log(str.match(reg));   // ['abc', index: 13, input: '24233\ndef345\nabc567', groups: undefined]

s修饰符

默认情况下的圆点(.)是匹配除换行符\n之外的任何字符,加上s之后,.中包含换行符\n。

1. 不加s修饰符

let reg = /abc./;
let str = 'abc\ndef345\nabc567';
console.log(str.match(reg));   // ['abc5', index: 11, input: 'abc\ndef345\nabc567', groups: undefined]

2. 使用s修饰符

let reg = /abc./s;
let str = 'abc\ndef345\nabc567';
console.log(str.match(reg));  // ['abc\n', index: 0, input: 'abc\ndef345\nabc567', groups: undefined]

y修饰符

使用g模式修饰符会一直匹配,但是如果加上y修饰符后如果从lastIndex开始匹配不成功就不继续匹配了。也就是说y模式在匹配不到时就会停止匹配。

1. 使用g模式

let reg = /abc/g;
let str = 'abcdefgshieabcso';
console.log(reg.exec(str));  // ['abc', index: 0, input: 'abcdefgshieabcso', groups: undefined]
console.log(reg.lastIndex);  // 3
console.log(reg.exec(str));  // ['abc', index: 11, input: 'abcdefgshieabcso', groups: undefined]
console.log(reg.lastIndex);  // 14
console.log(reg.exec(str));  // null
console.log(reg.lastIndex);  // 0
console.log(reg.exec(str));  // ['abc', index: 0, input: 'abcdefgshieabcso', groups: undefined]
console.log(reg.lastIndex);  // 3

从上述打印结果来看,使用g模式匹配时,如果从某个lastIndex开始匹配不到的话会继续往后匹配,如果匹配完了还会又从头开始匹配,一直这样循环。

2. 使用y模式

let reg = /abc/y;
let str = 'abcdefgshieabcso';
console.log(reg.exec(str));  // ['abc', index: 0, input: 'abcdefgshieabcso', groups: undefined]
console.log(reg.lastIndex);  // 3
console.log(reg.exec(str));  // null
console.log(reg.lastIndex);  // 0
console.log(reg.exec(str));  // ['abc', index: 0, input: 'abcdefgshieabcso', groups: undefined]
console.log(reg.lastIndex);  // 3
console.log(reg.exec(str));  // null
console.log(reg.lastIndex);  // 0

从上述打印结果来看,使用y模式匹配时,如果从某个lastIndex开始匹配不到的话会继续从头开始匹配,一直这样循环。

上面使用到了lastIndex,所以这里我们就来介绍一下lastIndex的用法。 lastIndex是RegExp对象的属性,它返回或者设置正则表达式开始匹配的位置。这个属性在使用时需要注意以下几点:

  • 必须和y模式或者g模式一起使用
  • 对exec方法有效
  • 匹配完成时,lastIndex会被重置为0

u修饰符

u修饰符一般使用的不多,通常是作为对特定字符的匹配使用的,这里我们了解一下即可。 每个字符都有属性,比如字母的属性是L,标点符号的属性是P,这些属性必须搭配u修饰符才生效。

// 使用\p{P}属性匹配标点符号
let reg = /\p{P}+/u;
console.log('这是一段神奇的故事!。'.match(reg));  // ['!。', index: 9, input: '这是一段神奇的故事!。', groups: undefined]

// 使用\p{L}属性匹配字母
let reg = /\p{L}+/u;
console.log('12sesbe是哦。'.match(reg));  // ['sesbe是哦', index: 2, input: '12sesbe是哦。', groups: undefined]

除了可以匹配特殊字符之外,还可以匹配不同的语言系统和字节编码

// 使用\p{sc=Han}匹配汉字
let reg = /\p{sc=Han}+/u;
console.log('12sesbe是哦。'.match(reg));  // ['是哦', index: 7, input: '12sesbe是哦。', groups: undefined]

// 匹配四个字符的UTF-16字节编码
let reg = /[𝒳𝒴]/;
console.log('123𝒳𝒴'.match(reg));  // ['\uD835', index: 3, input: '123𝒳𝒴', groups: undefined]

let reg = /[𝒳𝒴]/u;
console.log('123𝒳𝒴'.match(reg));  // ['𝒳', index: 3, input: '123𝒳𝒴', groups: undefined]

元字符

元字符表示某一类字符的格式,在正则表达式是最小元素,只代表单一字符。常用的元字符有以下几种 -- | -- | -- 元字符 | 说明 | 示例 \d | 匹配任意一个数字 | [0-9] \D | 匹配除了数字外的任意一个字符 | [^0-9] \w | 与任意一个英文字母,数字或下划线匹配 | [a-zA-Z0-9_] \W | 与除了英文字母,数字,下划线之外的任意一个字符匹配 | [^a-zA-Z0-9_] \s | 匹配任意一个空白字符,如空格,换行符\n, 制表符\t | [\n\t\f\v] \S | 与除了空白字符的任一字符匹配 | [^\n\t\f\v] . | 匹配除换行符之外的任意字符 | [^\n] \t | 匹配水平制表符 \n | 匹配换行符 \r | 匹配回车符 \v | 匹配垂直制表符 \f | 匹配换页符

从上面可以看出每一个大写字母和小写字母都是相反的,如\d和\D,\w和\W,\s和\S。如果要匹配所有字符只需要把大小写字母组合到一起即可。

let reg = /[\d\D]/;

量词

量词表示要匹配的字符或表达式的数量,因为字符或表达式默认只匹配一个,因此如果要匹配特定个数,需要结合量词一起使用。常用的量词有以下几种

符号说明
*匹配0次或多次
?匹配0次或1次
+匹配1次或多次
{n}匹配n次
{n,m}匹配n~m次
{n,}匹配至少n次

上面这几种量词在匹配的时候是贪婪的,正则表达式默认也是贪婪的,也就是会尽量匹配多的内容,与之相反的就是禁止贪婪,禁止贪婪对应的量词有以下几种:

符号说明
*?匹配任意次,一旦找到就尽可能停止, 因此匹配0次
+?匹配1次或多次,一旦找到就尽可能停止,因此匹配1次
??匹配0次或1次, 一旦找到就尽可能停止,因此匹配0次
{n,m}?匹配n~m次, 一旦找到就尽可能停止,因此匹配n次
{n,}?匹配至少n次, 一旦找到就尽可能停止,因此匹配n次

下面我们来看一下贪婪模式和禁止贪婪模式下的区别

let str = '39347233333dhjabcsd3';

let reg1 = /\d*/;
let reg2 = /\d*?/;
console.log(str.match(reg1));  // ['39347233333', index: 0, input: '39347233333dhjabcsd3', groups: undefined]
console.log(str.match(reg2));  // ['', index: 0, input: '39347233333dhjabcsd3', groups: undefined]

let reg1 = /\d?/;
let reg2 = /\d??/;
console.log(str.match(reg1));  // ['3', index: 0, input: '39347233333dhjabcsd3', groups: undefined]
console.log(str.match(reg2));  // ['', index: 0, input: '39347233333dhjabcsd3', groups: undefined]

let reg1 = /\d+/;
let reg2 = /\d+?/;
console.log(str.match(reg1));  // ['39347233333', index: 0, input: '39347233333dhjabcsd3', groups: undefined]
console.log(str.match(reg2));  // ['3', index: 0, input: '39347233333dhjabcsd3', groups: undefined]

let reg1 = /\d{2}/;
let reg2 = /\d{2}?/;
console.log(str.match(reg1));  // ['39', index: 0, input: '39347233333dhjabcsd3', groups: undefined]
console.log(str.match(reg2));  // ['39', index: 0, input: '39347233333dhjabcsd3', groups: undefined]

let reg1 = /\d{2,4}/;
let reg2 = /\d{2,4}?/;
console.log(str.match(reg1));  // ['3934', index: 0, input: '39347233333dhjabcsd3', groups: undefined]
console.log(str.match(reg2));  // ['39', index: 0, input: '39347233333dhjabcsd3', groups: undefined]

let reg1 = /\d{2,}/;
let reg2 = /\d{2,}?/;
console.log(str.match(reg1));  // ['39347233333', index: 0, input: '39347233333dhjabcsd3', groups: undefined]
console.log(str.match(reg2));  // ['39', index: 0, input: '39347233333dhjabcsd3', groups: undefined]

组和范围

在正则表达式里表示组和范围的有两种:字符集和组,其中字符集是用[]来表示,组使用()来表示。

字符集

字符集是用[]来包裹字符,表示匹配这里面的某个元字符,常见的有下面的这些

  • []: 只匹配其中的一个
  • [^]: 只匹配除了其中字符的任意一个元字符
  • [0-9]: 匹配0-9任何一个数字
  • [a-z]: 匹配小写a-z任何一个字母
  • [A-Z]: 匹配大写A-Z任何一个字母
let reg = /[0-9]{2,4}/;
console.log('sw127337w'.match(reg));  // ['1273', index: 2, input: 'sw127337w', groups: undefined]

let reg = /[^0-9]{2,4}/;
console.log('sw127337w'.match(reg));  // ['sw', index: 0, input: 'sw127337w', groups: undefined]

组是用()来包裹字符,表示这是一个整体,如果要匹配多个元字符,可以使用组。 组是一次匹配多个元字符,而字符集是匹配任意一个元字符。

每一个组包含有以下属性

  • 0: 匹配到的完整内容
  • 1,2...: 匹配到的组
  • index: 字符串中的位置
  • input: 字符串
  • groups: 字符串
let reg = /[0-9]{2,4}/;
console.log('sw127337w'.match(reg));  // ['1273', index: 2, input: 'sw127337w', groups: undefined]

解析打印结果:

  • '1273':匹配到的完整内容
  • index: 2:字符串中的位置
  • input: 'sw127337w':字符串
  • groups: undefined: 字符串,由于没有命名,因此是undefined
let reg = /(\w[0-9]{2,4})/;
console.log('sw127337w'.match(reg));  // ['w1273', 'w1273', index: 1, input: 'sw127337w', groups: undefined]

解析打印结果:

  • 'w1273':匹配到的完整内容
  • 'w1273': 匹配到的组, 上述例子中由于正则中没有组,所以没有这个属性
  • index: 1:字符串中的位置
  • input: 'sw127337w':字符串
  • groups: undefined: 字符串,由于没有命名,因此是undefined

如果是多个组

let reg = /(\w[0-9]{2,4})(\d{2,}\w)/;
console.log('sw127337w'.match(reg));  // ['w127337w', 'w1273', '37w', index: 1, input: 'sw127337w', groups: undefined]

如果是多个组的话,就会依次打印每个组的内容。

  • 'w127337w':匹配到的完整内容
  • 'w1273':匹配到的第一个组的内容
  • '37w':匹配到的第二个组的内容
  • index: 1:字符串中的位置
  • input: 'sw127337w':字符串
  • groups: undefined: 字符串,由于没有命名,因此是undefined

区分是第几个组:

通过数左边小括号,不论包裹得多么深,第一个左边小括号包裹的就是第一个组,第二个左边小括号包裹的就是第二个组,依次类推。

引用分组

在使用正则的时候,有时候我们可能需要使用前面的组里面的内容,如果重复写的话很麻烦,这里我们直接引用分组,\n在匹配时引用组,$n指在替换的时候使用匹配的组的数据。其中n表示的是第几个组。

let htmlStr = '<h1>我是标题1</h1><h2>我是标题2</h2><h3>我是标题3</h3>';
let reg = /<(h[1-6])>([\w\W]*)<\/\1>/g;
console.log(htmlStr.replace(reg, `<p>$2</p>`));  // <p>我是标题1</p><p>我是标题2</p><p>我是标题3</p>

组不参与匹配

let str = 'https://www.baidu.com\nhttp://test.com\nhttps://example.com';
let reg = /https?:\/\/((\w+\.)?\w+\.(com|org|cn))/gi;
while((v = reg.exec(str))) {
  console.dir(v);
}

打印结果如下:

image.png

如果不希望某些组参与匹配的话,可以将这个组使用(?:)处理。

let str = 'https://www.baidu.com\nhttp://test.com\nhttps://example.com';
let reg = /https?:\/\/((?:\w+\.)?\w+\.(?:com|org|cn))/gi;
while((v = reg.exec(str))) {
  console.dir(v);
}

效果如下:

image.png

给组设置别名

如果我们没有给组设置别名的话,在匹配出来的信息里面,groups的属性值是undefined。因此如果需要通过groups来判断因此需要设置别名。 设置组名使用?<>形式定义。

let reg = /(?<tag>\w[0-9]{2,4})(?<data>\d{2,}\w)/;
console.log('sw127337w'.match(reg)); 

效果如下:

image.png

全局匹配

下面我们来看一个例子

使用match匹配

let reg = /(\w[0-9]{2,4})(\d{2,}\w)/g;
console.log('sw127337w'.match(reg));  // ['w127337w']
for (const i of 'sw127337w'.match(reg)) {
  console.log(i)  
}  // w127337w

使用matchAll匹配

let reg = /(\w[0-9]{2,4})(\d{2,}\w)/g;
console.log('sw127337w'.matchAll(reg));
for (const i of 'sw127337w'.matchAll(reg)) {
  console.log(i)  
}

效果如下:

image.png

从上面的结果可以看出来,使用matchAll要比match匹配的更加深层次,也可以匹配更多的细节。 除了matchAll之外,exec也可以实现这样的效果。

字符方法

在String中,有以下几种支持正则表达式的方法

  • search(): 用于检索字符串中的指定的子字符串,返回索引位置
  • match(): 直接使用正则表达式搜索获取内容,使用g的话就不会有详细信息了
  • matchAll(): 使用正则表达式搜索, 返回迭代对象,但是要注意浏览器的兼容性
  • split(): 使用正则表达式分隔字符串
  • replace(): 进行正则替换
let reg = /\d+/ig;
console.log('我是233电话费'.search(reg));  // 2
console.log('我是233电话费'.match(reg));  // ['233']
console.log('我是233电话费'.matchAll(reg)); // RegExpStringIterator {}
for (const i of '我是233电话费'.matchAll(reg)) {
  console.log(i)    // ['233', index: 2, input: '我是233电话费', groups: undefined]
}

console.log('2023/03-22'.split(/-|\//));  //  ['2023', '03', '22']
console.log('2023/03-22'.replace(/-|\//, '-'));  // 2023-03-22

其中replace方法除了上面插入字符串之外,还可以插入以下变量:

  • $$: 插入一个'$'
  • $&: 插入匹配的子串
  • $`: 插入当前匹配的子串的左边的内容
  • $': 插入当前匹配的子串的右边的内容
  • $n: 假如第一个参数是RegExp对象,那么插入第n个括号匹配的字符串

除此之外,还可以使用回调函数处理复杂的替换逻辑。回调函数有以下几个变量:

  • search: 第一个变量,表示匹配的字符串
  • p1,p2,p3, ...: 假如第一个参数是RegExp对象,那么pn表示第n个括号匹配的字符串
  • index: 匹配到的子字符串在原字符串中的偏移量
  • string: 被匹配的原字符串
  • group: 命名捕获组匹配的对象
let reg = /(\w[0-9]{2,4})(\d{2,}\w)/;
'sw127337w'.replace(reg, (search, p1, p2, index, string, group) => {
  console.log('search', search);  // search w127337w
  console.log('p1', p1); // p1 w1273
  console.log('p2', p2); // p2 37w
  console.log('index', index); // index 1
  console.log('string', string); // string sw127337w
  console.log('group', group); // group undefined
}); 

正则方法

在正则表达式中,有以下几种方法

  • test: 检测输入的邮箱是否合法。返回布尔值
  • exec: 不使用g修饰符时与match方法使用相似,使用g修饰符后可以循环调用直到全部匹配完。 exec使用g模式修饰符时多次操作时使用同一个正则,即把正则定义为变量使用,最后匹配不到时返回null。
let reg = /[0-9]{2,4}/;
console.log(reg.test('sw127337w'));  // true

let reg = /[0-9]{2,4}/;
console.log(reg.exec('sw127337w'));  // ['1273', index: 2, input: 'sw127337w', groups: undefined]

let reg = /[0-9]{2,4}/;
let res = reg.exec('sw127337w');
console.log(res[0]);  // 1273
console.log(res[1]);  // undefined
console.log(res[2]);  // undefined

断言

断言通俗地理解就是正则的条件,断言的组成之一就是边界。对于文本、词或模式,边界可以用来表明它们的起始或终止部分。上面提到的边界符也是边界断言的一种方式。 除此之外,还有以下这些断言方式:

  • x(?=y): 先行断言:x 被 y 跟随时匹配 x。
  • x(?!y): 先行否定断言:x没有被y紧随时匹配x。
  • (?<=y)x: 后行断言:x跟随y的情况下匹配x。
  • (?<!y)x: 后行否定断言:x不跟随y时匹配x。
let reg = /(?=l)/g;
console.log('hello'.replace(reg, '@')); // he@l@lo
let reg = /(?!l)/g;
console.log('hello'.replace(reg, '@')); // @h@ell@o@
let reg = /(?<=l)/g;
console.log('hello'.replace(reg, '@')); // hel@l@o
let reg = /(?<!l)/g;
console.log('hello'.replace(reg, '@')); // @h@e@llo@

常用的正则表达式

匹配正整数

let reg = /^[1-9]\d*$/;

匹配正整数和0

let reg = /^(0|[1-9]\d*)$/;

匹配正数和两位小数

let reg = /^([1-9]\d*)+(.\d{1,2})?$/;

匹配正数和两位小数和0

let reg = /^(0|([1-9]\d*)+(.\d{1,2})?)$/;

匹配正整数和负整数

let reg = /^(\-)?[1-9]\d*$/;

匹配正整数和负整数和0

let reg = /^(0|(\-)?[1-9]\d*)$/;

匹配正数和负数和两位小数

let reg = /^(\-)?([1-9]\d*)+(.\d{1,2})?$/;

匹配正数和负数和两位小数和0

let reg = /^[+-]?(\d+\.\d{2}|\d+|\.\d{2})$/;

给数字添加千位分隔符

给数字增加千位符,其实就是如果某个数字后面有三位数字,那么就在这个数字后面添加一个分隔符。所以这里要用到先行断言

let reg = /(?=(\d{3})+$)/g;
console.log('15273748'.replace(reg, ',')); // 15,273,748

匹配固定电话

let reg = /^(0\d{2,3}-?|\(0\d{2,3}\))[1-9]\d{6,7}$/;

匹配手机号

let reg = /^[1][3,4,5,6,7,8,9][0-9]{9}$/;

匹配邮箱

let reg = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;

匹配用户名

这个用户名要和具体的公司规定来设置

let reg = /^[a-zA-Z0-9_-]{4,16}$/;

匹配密码

密码长度6-12位,由数字、小写字符和大写字母组成,但必须至少包括2种字符。

// 取并集
let reg = /((?=.*[0-9])(?=.*[a-z])|(?=.*[0-9])(?=.*[A-Z])|(?=.*[a-z])(?=.*[A-Z]))^[0-9A-Za-z]{6, 12}$/;

// 取补集
let reg = /(?!^[0-9]{6,12}$)(?!^[a-z]{6,12}$)(?!^[A-Z]{6,12}$)^[0-9A-Za-z]{6,12}$/;

匹配身份证

let reg = /^(\d{15}|\d{17}[\dxX])$/;

匹配url

let reg = /((http|https):\/\/([\w\-]+\.)+[\w\-]+(\/[\w\u4e00-\u9fa5\-\.\/?\@\%\!\&=\+\~\:\#\;\,]*)?)/ig

匹配IP地址

let reg = /^((0{0,2}\d|0?\d{2}|1\d{2}|2[0-4]\d|25[0-5])\.){3}(0{0,2}\d|0?\d{2}|1\d{2}|2[0-4]\d|25[0-5])$/

它是一个多选结构,分成5个部分:

  • 0{0,2}\d,匹配一位数,包括0补齐的。比如,9、09、009;
  • 0?\d{2},匹配两位数,包括0补齐的,也包括一位数;
  • 1\d{2},匹配100到199;
  • 2[0-4]\d,匹配200-249;
  • 25[0-5],匹配250-255。

匹配windows操作系统文件路径

// 盘符:\文件夹\文件夹\文件夹\文件名
// 文件夹名不能包含一些特殊字符:[^\\:*<>|"?\r\n/]+\\

// let reg = /^[a-zA-Z]:\\([^\\:*<>|"?\r\n/]+\\)*([^\\:*<>|"?\r\n/]+)?$/;

匹配日期

let reg = /^\d{4}[-\/](0[0-9]|1[0-2])[-\/](0[1-9]|[12][0-9]|3[01])$/;
console.log(reg.test('2023/03/26'));  // true

如果要匹配2023/3/26这种没有补位0的格式的

let reg = /^\d{4}[-\/]([1-9]|0[0-9]|1[0-2])[-\/]([1-9]|0[1-9]|[12][0-9]|3[01])$/;
console.log(reg.test('2023/3/2'));  // true

匹配时间

let reg = /^[0-1][0-9]|2[0-3]:[0-5][0-9]$/;
console.log(reg.test('16:54'));  // true

匹配颜色

let reg = /^#[0-9a-fA-F]{6}|[0-9a-fA-F]{3}$/g;
let string = "#ffbbad #Fc01DF #FFF #ffE";
console.log(string.match(reg));

去除首尾空格

let reg = /^\s+|\s+$/;
console.log(str.replace(reg, ''));

将每个单词的首字母转换为大写

let reg = /(?:^|\s)\w/g;
const titleize(str) {
    return str.replace(reg, (a) => {
        return a.toUpperCase();
    })
}

驼峰化

将连字符转成驼峰

let reg = /[-_\s]+(.)?/g;
const titleize(str) {
    return str.replace(reg, (a) => {
        return a ? a.toUpperCase() : '';
    })
}

中划线化

const dasherize = (str) => {
	return str.replace(/([A-Z])/g, '-$1').replace(/[-_\s]+/g, '-').toLowerCase();
}
console.log( dasherize('MozTransform') ); // -moz-transform

html转义和反转义

const escapeHTML = (str) => {
	let escapeChars = {
	  '¢' : 'cent',
	  '£' : 'pound',
	  '¥' : 'yen',
	  '€': 'euro',
	  '©' :'copy',
	  '®' : 'reg',
	  '<' : 'lt',
	  '>' : 'gt',
	  '"' : 'quot',
	  '&' : 'amp',
	  '\'' : '#39'
	};
	return str.replace(new RegExp('[' + Object.keys(escapeChars).join('') +']', 'g'), function(match) {
		return '&' + escapeChars[match] + ';';
	});
}
console.log( escapeHTML('<div>Blah blah blah</div>') ); // &lt;div&gt;Blah blah blah&lt;/div&gt;

匹配成对标签

let reg = /<([^>]+)>[\d\D]*<\/\1>/;

本篇文章是从正则表达式的使用层面整理出来的,如果你想要更加深入理解正则表达式,可以阅读这篇文章(juejin.cn/post/684490…)