正则表达式题目+讲解

580 阅读5分钟

最近在研究正则,看了很多文章发现写的都非常好,但是真给几个题目做做,还真做不出来,下面我们就根据题目去讨论一下正则,相信通过这些题目,我们再去看大佬的文章或许会收获更多!

一、创建正则

  • 构造函数创建
const reg = new RegExp(/a/); // 匹配含有字母a
  • 正则字面量
const reg2 = /abc/; // 匹配字母abc
const reg3 = /[abc]/; // 匹配字母a,或者b,或者c

二、正则的组成

  • 正则的组成: 普通字符 + 元字符
  • 普通字符: 大小写字母, 数字
  • 元字符: 在正则里面有特殊含义的

元字符

匹配区间正则表达式含义
除了换行的任意的字符.句号,除了句子结束符
数字[0-9]\ddigit
非数字 除了[0-9]\Dnot digit
字符(大小写字母 数字 _)\wword
非字符\Wnot word
不可见字符(空格 换行 制表符(tab))\sspace
可见字符\Snot space
但是如果我想要匹配'.'这个符号就要使用 '\' 进行转译
/ 匹配小数点
// 需要对 . 进行转义,  \.
console.log(/\./.test("100.5"));  // true
console.log(/\./.test("1005"));   // false

转译字符还有一个作用,就是这个字符不是特殊字符,使用转译符号后就让他拥有了特殊的含义。比如说元字符,还有一些特殊字符

特殊字符正则表达式含义
换行符\nnew line
回车符\rreturn
空白符\sspace
制表符\ttab
我们来做一些题目
var reg1 = /abc/
console.log(reg1.test("a")); // false
console.log(reg1.test("aabca")); // true
匹配abc

var reg2 = /\d/
console.log(reg2.test('abc123')) // true
reg2 = /\D/
console.log(reg2.test('abc123')) // true
匹配数字和非数字

var reg3 = /\./
console.log(reg3.test('100.5')) // true
console.log(reg3.test('1005')) // false

如果我要匹配两个怎么办呢?
console.log(/(f|b)oot/.test("f"));      // false
console.log(/(f|b)oot/.test("foot"));   // true
console.log(/(f|b)oot/.test("boot"));   // true
console.log(/(f|b)oot/.test("fboot"));  // true

由题目的最后一题我们引出[] 如果我要匹配a或者b或者c该怎么办?

let reg = /a|b|c/
let reg1 = [abc]

[]的解释说明

  • [] ===> 在正则里面一个字符的位置,在[]里面可以出现的字符,可以使用“-”表示范围
  • [^] ===> ^在[]里面,表示非的意思
  • [^abc] ===> 表示不能是a,或者不能是b,或者不能是c,除了abc都行
// /[abc]/   ==> a 或者 b 或者 c
// /[a-z]/   ==> 是一个字符, 字符可以是 a-z 的其中一个
// /[A-Z]/   ==> 是一个字符, 字符可以是 A-Z 的其中一个
// /[0-9]/   ==> 是一个字符, 字符可以是 0-9 的其中一个
// /[a-zA-Z0-9]/   ==> 是一个字符, 字符可以是 a-z 或者 A-Z 或者  0-9 的其中一个

console.log(/[abc]/.test("a")); // true
console.log(/[abc]/.test("b")); // true
console.log(/[abc]/.test("c")); // true
console.log(/[a-z]/.test("a123")); // true
console.log(/[a-z]/.test("123")); // false
console.log(/[^abc]/.test("abc")); // false
console.log(/[^abc]/.test("ade")); // true,   只要满足了正则的规律,就返回true
console.log(/[^0]/.test("0123")); // true
console.log(/[^0]/.test("0")); // false

三、循环与重复

正则表达式含义解释
*出现 0次到多次 {0,}>= 0
+出现 1次到多次{1,}>= 1
?出现 0次到1次{0,1}0 || 1
{m,n}出现 m次到n次
{m,}出现 m次以上
{m}出现m次
{0,m}出现最多m次

我觉得先做一个面试题,根据面试题我们在进行讲解效果会好很多

const target = '111,222,333,aa,  ,!@?'
// 1.1 匹配target中的数字
// 1.2 将特殊符号(除了','号)替换为\*

target.match(/\d+/g)
target.replace(/[^,\w]/g,'*')
// 讲解:
// 1. 字符串的match()方法:
//    会返回数组,数组里面就是字符串中符合正则的每一项, 匹配不到返回null
// 2. 元字符 + 适用于要匹配同个字符出现1次或多次的情况 >=1
      元字符 ? 0 | 1
      元字符 * >= 0
      特定次数:
      {x}: x次
      {min, max}: 介于min次到max次之间
      {min, }: 至少min次
      {0, max}: 至多max次

题目里提到了g这就引出了

四、字符串边界

接下来我们还需要位置边界的匹配。在长文本字符串查找过程中,我们常常需要限制查询的位置。比如我想要全局匹配,我想要不区分大小写

边界和标志正则表达式含义
单词边界\bboundary
非单词边界\Bnot boundary
字符串开头箭头就是开头
字符串结尾$做事的结果都会有钱$
多行模式mmultiple of lines
忽略大小写iignore case, case-insensitive
全局模式gglobal
  • \b和\B

\b是单词边界,具体就是\w和\W之间的位置,也包括\w和^之间的位置,也包括\w和$之间的位置。

const reg1 = "[JS] Lesson_01.mp4".replace(/\b/g, '#');
console.log(reg1); // "[#JS#] #Lesson_01#.#mp4#"
const reg2 = "[JS] Lesson_01.mp4".replace(/\B/g, '#');
console.log(reg2); // "#[J#S]# L#e#s#s#o#n#_#0#1.m#p#4"
  • ^和$
// 把字符串的开头和结尾加上|
const reg1 = "hello".replace(/^|$/g,'|')
console.log(reg1) // "|hello|"
  • g和m
const result = "I\nlove\njavascript".replace(/^|$/gm, '#');
console.log(result);
/*
#I#
#love#
#javascript#
*/
 // 给一个连字符串例如:get-element-by-id转化成驼峰形式。
 let str = 'get-element-by-id'
 let reg = /-\w/g
 str.replace(reg,v => v.slice(1).toUpperCase())
 
// 验证座机电话
// 规律:021-29109210 0557-10928380
// 区号:3-4位数字 首位是0 次位不能为0的数字 1-2位数字
// 座机:7-8位数字 首位2-8的数字 6-7位数字

let reg = /^0\[1-9]\d{1,2}-[2-8]\d{6,7}$/
// 验证手机号码
// 规律:13900000000
// 十一位数字 首位1 次位3-9 9位数字

let reg = /^1[3-9]\d{9}$/
// 验证邮箱
// 规律:数字 字母 _ . - @ 数字 字母 _ .字母

let reg = /^[\w\.-]+@\w+(\.[a-z]+)+$/
// 验证姓名
// 规律:汉字 2-6位
let reg = /^[\u4e00-\u9fa5]{2,6}$/

当我以为正则学的差不多的时候,有一个题目难住了我

// 数字的千位分隔符表示法"12345678",变成"12,345,678"
  • (?=p)和(?!p)

(?=p),其中p是一个子模式,即p前面的位置

比如(?=l),表示'l'字符前面的位置,例如:

var result = "hello".replace(/(?=l)/g, '#');
console.log(result); 
// => "he#l#lo"

而(?!p)就是(?=p)的反面意思,比如:

var result = "hello".replace(/(?!l)/g, '#');
console.log(result); 
// => "#h#ell#o#"

经过上面的总结现在给出字符串的千分位分隔符表示法

let string = "12345678123456789";
const reg = /(?!\b)(?=(\d{3})+\b)/g;

let result = string.replace(reg, ',')
console.log(result); 
// => "12,345,678,123,456,789"

另一种数字的千分位分隔符表示法(不推荐)

let num = 10329203.23
console.log(num.toLocaleString())