正则表达式小记

最近工作需要对诸如手机号码进行脱敏,正好巩固了一下正则表达式的使用,写下文章记录一下。

什么是正则表达式

引用一下MDN上面的注解:

正则表达式是用于匹配字符串中字符组合的模式。在 JavaScript中,正则表达式也是对象。这些模式被用于 RegExp 的 exec 和 test 方法, 以及 String 的 match、matchAll、replace、search 和 split 方法。本章介绍 JavaScript 正则表达式。

编写正则表达式

按照上文的解释,我们有两种方法来创建正则对象:

  1. 对象字面量:
var reg = /123/
  1. 通过原生RegExp对象创建:
var reg = new RegExp('123')

特殊字符模式

正则表达式是有简单字符特殊字符组成的,比方说1, 2, 3, ‘a’, 'b’这种是简单字符;像\d, \w, \s这些是特殊字符。关于特殊字符的含义我就不说了,以下列出常用几个,具体的可以去查文档:MDN 正则表达式

  1. \d: 数字,比方说[0 - 9]
  2. \D: 非数字,比方说[^ 0 - 9]
  3. \w: 单字字符(数字,字母,下划线),如:[a-zA-Z_0-9]
  4. \W: 匹配一个非单字字符。等价于 [^A-Za-z0-9_]。
  5. \s:匹配一个空白字符,包括空格、制表符、换页符和换行符。
  6. \S: 匹配一个非空白字符。

相信大家发现一些规则,小写字母都是匹配相应值,对应的大写字母就在原基础上取非。怎么样,很好记吧;再来几个日常用到的关于个数匹配的解释:

  1. {n}: n 是一个正整数,匹配了前面一个字符刚好出现了 n 次。
  2. {n,}: n是一个正整数,匹配前一个字符至少出现了n次。
  3. {n,m}: n 和 m 都是整数。匹配前面的字符至少n次,最多m次。如果 n 或者 m 的值是0, 这个值被忽略。
  4. [abc]: 一个字符集合。匹配方括号中的任意字符,包括转义序列。

例子

话不多说了,正式开始写例子了:

  1. 电话号码脱敏处理。比如说:输入:13580378064 输出:135****8064
// 咱们先来一把常规方法处理
function decodeMobile(num) {
 let numStr = num.toString()
 if (!numStr || numStr.length < 11) return num

 return numStr.substring(0, 3) + '****' + numStr.substring(7)
}

言归正传,上正餐:

第一版
function decodeMobile(num) {
  let numStr = num.toString()
  if (!numStr || numStr.length < 11) return num

  return numStr.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
}

好,这个正则出现特殊字符 () $1 $2都是干嘛的呢,我们来看看:
引用一下MDN关于上面三个特殊字符的解释:

(x) : 像下面的例子展示的那样,它会匹配 ‘x’ 并且记住匹配项。其中括号被称为捕获括号。
模式 /(foo) (bar) \1 \2/ 中的 ‘(foo)’ 和 ‘(bar)’ 匹配并记住字符串 “foo bar foo bar” 中前两个单词。模式中的 \1 和 \2 表示第一个和第二个被捕获括号匹配的子字符串,即 foo 和 bar,匹配了原字符串中的后两个单词。注意 \1、\2、…、\n 是用在正则表达式的匹配环节,详情可以参阅后文的 \n 条目。而在正则表达式的替换环节,则要使用像 $1、2...2、...、n 这样的语法,例如,‘bar foo’.replace(/(…) (…)/, '$2 1)1')。& 表示整个用于匹配的原字符串。

也就是说,(\d{3}) 会捕获手机号的前三位数字,并且记录匹配项,然后用$1 存起来,后续替换掉 。
但是第一版还有个问题,就是没有校验输入的手机号是不是数字,如果是别的字符显然不符合要求,接下来我们写第二版:

第二版
function decodeMobile(num) {
	let reg = /^1\d{10}$/  // 以1开头的11位数字
	if (num && !reg.test(num)) {
		return num
	}
	return num.toString().replace(/(\d{3})\d{4}(\d{3})/, '$1****$2')
}

mocha写一下基本的测试用例(关于测试用例的编写,这里不做阐述,后续再写一篇小记记录一下),校验一下结果

describe('手机号脱敏', function() {
  it('输入:13580378064  输出: 135****8064', function() {
    assert.equal(decodeMobile(13580378064), '135****8064')
  })
  it('输入:23580378064  输出: 23580378064', function() {
    assert.equal(decodeMobile(23580378064), '23580378064')
  })
  it('输入:123456789abc  输出:123456789abc', function() {
    assert.equal(decodeMobile('123456789abc'), '123456789abc')
  })
  it('输入:""  输出:""', function() {
    assert.equal(decodeMobile(''), '')
  })
})

如下图所示:
在这里插入图片描述
2. 电子邮箱匹配
诸如[email protected] [email protected],这些都是邮箱地址,这次我们来从一串字符中读取出类似的字符串出来,直接上代码:

第一版
function getEmail(str) {
	const reg = new RegExp(/\w+@\w+\.com/)
	return str.match(reg)
}

测试如下:
在这里插入图片描述
当输入: “[email protected], test, [email protected]”,并没有全局搜索,而是找到第一个结果之后就返回结果数组,这时候要加上 g 全局匹配

第二版
function getEmail(str) {
  var reg = new RegExp(/\w+@\w+\.com/g)
  return str.match(reg)
}

结果很完美,如图:
在这里插入图片描述
邮箱的规则暂时想到这么多,貌似还有一些特殊情况还没考虑到,关于正则的小记先暂且一段落吧。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章