正則表達式小記

最近工作需要對諸如手機號碼進行脫敏,正好鞏固了一下正則表達式的使用,寫下文章記錄一下。

什麼是正則表達式

引用一下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)
}

結果很完美,如圖:
在這裏插入圖片描述
郵箱的規則暫時想到這麼多,貌似還有一些特殊情況還沒考慮到,關於正則的小記先暫且一段落吧。

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