三分钟正则之基础了解

本人曾经对正则表达式是又爱又恨, 爱的是网上有很多别人写好的正则表达式可以拿到工作中直接使用简化工作代码, 恨的是一旦正则匹配的需求调整苦于看不懂别人写好的正则表达式不知道如何修改。 这个专栏就把这些日子自己研究的正则学习心得分享给大家, 希望能对大家有所帮助。

1. 首先看看正则优点

需求: 将‘ab c d e’字符串中的空格去掉

不使用正则:

// 将字符串 -> 通过空格转为数组 -> 在变为字符串
let str = 'ab c d e';
let strToArr = str.split(' ');
let ArrToStr = strToArr.join('');
复制代码

使用正则:

// 直接匹配出空格替换为空串
let str = 'ab c d e';
let res = str.replace(/\s/g, '');
复制代码

从上面对数据的处理我们可以看出正则的优势:

  1. 方便, 只需要一行代码就可以解决问题;
  2. 高效, 在原有的数据类型上进行处理而无需改变数据类型;

但是也正则也有自己的缺点:

对初学者不友好, 可能看不懂\s g代表着什么第一眼看上去很麻烦, 但是随着对正则的掌握越来越熟练后这个缺点也不复存在了, 只要了解了它的规则就可以以很少的代码写出js中复杂的匹配规则, 下面来学习一下正则中的基本规则吧!

2. 正则基本规则

1. 两种形式

一种是实例化形式, 一种是字面量形式. 一般都是使用字面量形式去声明一个正则, 实例化形式一般都是在匹配内容是一个变量的情况下才使用, 这个后期会有说明可以先不看.

// 1. 构造函数实例化形式
let reg = new RegExp('test', 'g');
let str = 'this is test';
reg.test(str);

// 2. 直接字面量形式
let reg = /test/g
let str = 'this is test'
str.test(reg)
复制代码

2. 以 /test/g 为例说明这个正则含义

这个表达式可以分两段进行理解:

  1. /test/ 两个斜杠中的test代表我要匹配的内容中是否包含test这个字符串
  2. /test/后面的g字母代表着匹配的范围, 此时代表着匹配全局,其实很好理解g就是英文global的缩写

明白了上面两段我们就可以很好的看出这个正则的作用了: 全局匹配一个字符看里面是否至少含有一个test的字符串

let reg = /test/g

// 1. 字符串中不包含test情况
'tes'.match(reg) -> null

// 2. 字符串包含且只有一个test情况
'test is a'.match(reg) -> ['test']

// 3. 字符串包含且有多个test的情况
'test is a test'.match(reg) -> ['test', 'test']
复制代码

我们发现多个test都会被匹配出来, 此时就是因为g操作了匹配的范围进行了全局匹配,如果我们去掉g,则只会匹配出前面的test

let reg = /test/;
'test is a test'.match(reg) -> ['test'] (当然整体的值是['test', index: 0, input: 'test is a test', groups: undefined], 这个后面会详细解释, 这里只需要看出只匹配出一个test结果就好)
复制代码

由此可见正则最后面的字母代表着匹配条件, 除了g全局匹配以外还有其他的例如, i忽略大小写, m匹配多行

// 没有i的情况下对大小写敏感, 无法匹配出字符串中的test
let reg = /TEST/g;
console.log('test is a test'.match(reg)); // null

// i 意思是忽略大小写
let reg = /TEST/gi;
console.log('test is a test'.match(reg));  // ['test', 'test']

// m 多行匹配 修饰符的作用 现在把Test开头的字符串匹配出来
let str = 'Test is a test.\nTest is here'
let reg = /^Test/g  -> 只能匹配到第一个Test, 不能匹配换行后的Test
let reg = /^Test/gm -> 多行匹配\n后为第二行的Test也能匹配出来

复制代码

3. [] 括号表达式理解

在上面的例子中我们可以看出, /test/匹配成功的关键点是字符串中必须有完整的'test', 如果少一个t ('tes') 也不会匹配成功, 如果我们想一位一位的匹配那么就需要使用[]表达式了, 比如我有一个需求匹配一个字符串中包含'abc'或者包含'bbc'这两种情况都能成立,那么写法就是:

// [ab] -> 意思代表开头的这一位可以是a也可以是b
let reg = /[ab]bc/g
复制代码

遇到[]时候不用慌, 可以简单理解为有几个括号就是匹配几位, 例如:

// 现在匹配三个字符, 第一位是w或者x, 第二位x或者y, 第三位z
let reg = /[wx][xy][z]/g
复制代码

4. 正则默认的匹配规则

正则中有两个很重要的点

  1. 默认贪婪模式, 能匹配多个就不会匹配少
  2. 匹配过了的就不会在重新匹配

举个例子:

// 贪婪模式的效果: 匹配字符串a连续出现一次或者多次
let reg = /a+/g;
let str = 'this a dog or aa god or aaa good';
str.match(reg); ->  ['a', 'aa', 'aaa']
复制代码

从上面的结果上能发现结果并不是 [a, a, a, a, a, a]. 简单的说明一下匹配规则:

  1. 首先从左往右开始匹配,匹配到了第一个a发现只有一个同时符合要求并且把这个a记录了下来;
  2. 从第一个a继续往后开始匹配发现or后面有两个连续的aa也符合的正则的匹配条件,并且默认是贪婪模式则将aa这个值也记录了下来;
  3. 然后从aa后面继续往后查询发现aaa也匹配了出来.
  4. 直到匹配最后,结果也就是['a', 'aa', 'aaa']

5. 结尾

本篇主要简单讲解了一下正则的基础用法和基础规则, 其实里面还有很多知识点例如如何使用正则进行复杂规则的匹配、实现模板字符串的替换、()表达式的使用以及重难点字符串的replace方法和正则表达式的搭配使用等等。当然这些知识需要在了解完所有正则的基础后才能去学习, 那么下一次来分享一下正则中的的量词元字符吧。

猜你喜欢

转载自juejin.im/post/7032268272401645582