JavaScript正則深入以及10個非常有意思的正則實戰

echa攻城獅 發佈 2020-05-11T22:34:23+00:00

對於正則的基本用法筆者這裡就不總結了,這裡重點介紹一些比較有用且難懂的知識點.在最後筆者會寫10個經典的正則案例, 供大家學習參考, 或者在工作中直接使用.let str = 'xuxi is xuxi is'let reg = / \1 \2/g。


作者:徐小夕

轉發連結:https://mp.weixin.qq.com/s/2Bk8lkRCNyaTWYtIB0oYVg

前言

熟悉我的朋友可能會知道,我一向是不寫熱點的。為什麼不寫呢?是因為我不關注熱點嗎?其實也不是。有些事件我還是很關注的,也確實有不少想法和觀點。但我一直奉行一個原則,就是:要做有生命力的內容。

對於前端工程師來說, 正則表達式也許是javascript語言中最晦澀難懂的, 但是也往往是最簡潔的.工作中遇到的很多問題,諸如搜索,查找, 高亮關鍵字等都可以使用正則輕鬆解決,所以有句話說的好:

正則用的好, 加班遠離我.

今天筆者就復盤一下javascript正則表達式的一些使用技巧和高級API, 並通過幾個實際的案例,來展現正則表達式的魅力.如果大家覺得正則表達式理解起來很麻煩,也可以使用如下在線網站, 只需要輸入你的正則表達式, 它就能以圖形的方式將你的正則展示出來:

你將收穫

  • 模式匹配的用法(x)
  • 非捕獲括號的模式匹配(?:x)
  • 先行斷言x(?=y)
  • 後行斷言(?<=y)x
  • 正向否定查找x(?!y)
  • 反向否定查找(?<!y)x
  • 字符集合和反向字符集合的用法[xyz]/[^xyz]
  • 詞邊界和非單詞邊界匹配/b/B
  • 空白字符/非空白字符匹配/s/S
  • 單字字符/非單字字符匹配/w/W
  • 正則10大應用案例

正文

對於正則的基本用法筆者這裡就不總結了,這裡重點介紹一些比較有用且難懂的知識點.在最後筆者會寫10個經典的正則案例, 供大家學習參考, 或者在工作中直接使用.


以上幾點應用筆者在下文中會寫幾個例子來講解.

模式匹配的用法(x)

模式匹配主要用來匹配某一類字符串並記住匹配項.

案例:

let str = 'xuxi is xuxi is'
let reg = /(xuxi) (is) \1 \2/g
reg.test(str)  // true    (1)
str.replace(reg, '$1 $2')  // xuxi is  (2)複製代碼

解釋: 其中括號被稱為捕獲括號, 模式中的 \1 和 \2 表示第一個和第二個被捕獲括號匹配的子字符串,即 xuxi 和 is,匹配了原字符串中的後兩個單詞, 因此(1)中運行的結果為true. 當我們在字符串中使用replace時, 我們可以使用$1, $2這樣的方式獲取第n個匹配項,並用來替換字符串. 如(2)中的運行結果.

非捕獲括號的模式匹配(?:x)

主要用來匹配某一類字符串但不記住匹配項.

案例:

let str = 'xuxixuxi'
let reg = /(?:xuxi){1,2}/g
reg.test(str)  // true    (1)複製代碼


解釋: 其中(?:)被稱為非捕獲括號, 我們可以使用它匹配一組字符但是並不記住該字符,一般用來判斷某類字符是否存在於某字符串中.

先行斷言x(?=y)

先行斷言: 匹配'x'僅僅當'x'後面跟著'y'.

案例:

let str = '王者融化'
let reg = /王(?=者)/
reg.test(str)  // true    (1)複製代碼


解釋: /王(?=者)/會匹配到"王"僅當它後面跟著"者".但是"者"不屬於匹配結果的一部分.

後行斷言(?<=y)x

後行斷言: 匹配'x'僅當'x'前面是'y'.

案例:

let str = 'xuxiA'
let reg = /(?<=xuxi)A/
reg.test(str)  // true    (1)複製代碼

解釋: /(?<=xuxi)A/會匹配到A僅當它前面為xuxi.但是xuxi不屬於匹配結果的一部分.

正向否定查找x(?!y)

正向否定查找: 僅僅當'x'後面不跟著'y'時匹配'x'.

案例:

let str = '3.1415'
let reg = /\d+(?!\.)/
reg.exec(str)  // [1415]   (1)複製代碼

解釋: 其中/\d+(?!.)/匹配一個或多個數字,若且唯若它後面沒有小數點時, 所以(1)中執行後會匹配到1415而不是3.1415

反向否定查找(?<!y)x

反向否定查找: 僅僅當'x'前面不是'y'時匹配'x'.

案例:

let str = '3.1415'
let reg = /(?<!\.)\d+/
reg.exec(str)  // [3]    (1)複製代碼

解釋: /(?<!.)\d+/匹配一個數字,若且唯若前面字符不是.時,此時將匹配3.

字符集合和反向字符集合的用法 [xyz] / [^xyz]

[xyz]: 一個字符集合。匹配方括號中的任意字符,包括轉義序列。你可以使用破折號(-)來指定一個字符範圍。

[^xyz]: 一個反向字符集。也就是說,它匹配任何沒有包含在方括號中的字符。你可以使用破折號(-)來指定一個字符範圍。任何普通字符在這裡都是起作用的

案例:

let str = 'abcd'
let reg1 = /[a-c]+/
let reg2 = /[^d]$/
reg1.test(str)  // true    (1)
reg2.test(str)  // false    (2)複製代碼

解釋: (1)中將返回true因為字符串中包含a-c中的字符, (2)中獎返回false, 因為字符串結尾為d, 但正則reg2需要匹配結尾不為d的字符串.

詞邊界和非單詞邊界匹配\b\B

\b 匹配一個詞的邊界。一個詞的邊界就是一個詞不被另外一個「字」字符跟隨的位置或者前面跟其他「字」字符的位置,例如在字母和空格之間。注意,匹配中不包括匹配的字邊界。換句話說,一個匹配的詞的邊界的內容的長度是0。

\B 匹配一個非單詞邊界。匹配如下幾種情況:(1)字符串第一個字符為非「字」字符 (2)字符串最後一個字符為非「字」字符 (3)兩個單詞字符之間 (4)兩個非單詞字符之間 (5)空字符串

案例:

let str = 'xuxi'
let reg1 = /xi\b/
let reg2 = /xu\B/
reg1.exec(str)  // [xi]    (1)
reg2.exec(str)  // [xu]    (2)複製代碼



解釋: (1)中匹配到了單詞邊界,即xi, 為該字符串的末尾.(2)中應為xu為非單詞邊界,所以會被其匹配到.

空白字符/非空白字符匹配\s\S

\s: 匹配一個空白字符,包括空格、制表符、換頁符和換行符.

\S: 匹配一個非空白字符

案例:

let str = 'xuxi is'
let reg1 = /.*\s/g
let reg2 = /\S\w*/g
reg1.exec(str)  // [xuxi]    (1)
reg2.exec(str)  // [xuxi]    (2)複製代碼

解釋: (1)和(2)中執行之後都將匹配xuxi, 一個是空白字符之前的匹配, 一個是非空白字符的匹配.

單字字符/非單字字符匹配\w/W

\w: 匹配一個單字字符(字母、數字或者下劃線)。等價於 [A-Za-z0-9_]。

\W: 匹配一個非單字字符。等價於 [^A-Za-z0-9_]

由於以上2種模式比較簡單,這裡就不一一介紹了.

正則10大應用案例

接下來筆者將總結幾個使用正則的實際應用,供大家學習和參考.

1. 去除字符串內指定元素的標籤

function trimTag(tagName, htmlStr) {
  let reg = new RegExp(`<${tagName}(\\s.*)*>(\\n|.)*<\\/${tagName}>`, "g")
  return htmlStr.replace(reg, '')
}複製代碼

2. 短橫線命名轉駝峰命名

// 短橫線轉駝峰命名, flag = 0為小駝峰, 1為大駝峰
function toCamelCase(str, flag = 0) {
  if(flag) {
    return str[0].toUpperCase() + str.slice(1).replace(/-(\w)/g, ($0, $1) => $1.toUpperCase())
  }else {
    return str.replace(/-(\w)/g, ($0, $1) => $1.toUpperCase())
  }
}複製代碼

3. 實現一個簡單的模板引擎

關於實現一個模板引擎, 實現中用到了大量的正則,建議感興趣的可以直接看實現一個簡單的模板引擎.

4. 去除字符串中的空格符

function trimAll(str) {
  return str.replace(/\s*/g,"")
}複製代碼

5. 判斷指定格式的數據輸入合法性

function numCheck(str, specialNum) {
  if(str.indexOf(',') > -1) {
      return str.splite(',').every(item=>this.numCheck(item));
  } else {
      return str.split(specialNum).length === 2;
  }
}複製代碼

6. 去除url參數字符串中值為空的欄位

// 去除url參數字符串中值為空的欄位
const trimParmas = (parmaStr:string = '') => {
  return parmaStr.replace(/((\w*?)=&|(&\w*?=)$)/g, '')
}複製代碼

7. 將瀏覽器參數字符串轉化為參數對象

function unParams(params = '?a=1&b=2&c=3') {
  let obj = {}
  params && params.replace(/((\w*)=([\.a-z0-9A-Z]*)?)?/g, (m,a,b,c) => {
    if(b || c) obj[b] = c
  })
  return obj
}複製代碼

8. 計算字符串字節數

/**
 * 計算字符串字節數
 * @param str
 * @desc 一個中文占2個字節, 一個英文占一個字節
 */
function computeStringByte(str) {
  let size = 0,
  strArr = str.split(''),
  reg = /[\u4e00-\u9fa5]/   // 判斷是否為中文
  for(let i = strArr.length; i--; i>=0) {
    if(reg.test(strArr[i])) {
      size+= 2
    }else {
      size += 1
    }
  }
  return size
}複製代碼

9. 匹配是否包含中文字符

function hasCn(str) {
  let reg = /[\u4e00-\u9fa5]/g
  return reg.test(str)
}複製代碼

10. 實現搜索聯想功能

function searchLink(keyword) {
  // 模擬後端返回數據
  let list = ['abc', 'ab', 'a', 'bcd', 'edf', 'abd'];
  let reg = new RegExp(keyword, 'i');
  return list.filter(item => reg.test(item))
}

推薦JavaScript經典實例學習資料文章

《前端面試者經常忽視的一道JavaScript 面試題》

《一行JS代碼實現一個簡單的模板字符串替換「實踐」》

《JS代碼是如何被壓縮的「前端高級進階」》

《前端開發規範:命名規範、html規範、css規範、js規範》

《【規範篇】前端團隊代碼規範最佳實踐》

《100個原生JavaScript代碼片段知識點詳細匯總【實踐】》

《關於前端174道 JavaScript知識點匯總(一)》

《關於前端174道 JavaScript知識點匯總(二)》

《關於前端174道 JavaScript知識點匯總(三)》

《幾個非常有意思的javascript知識點總結【實踐】》

《都2020年了,你還不會JavaScript 裝飾器?》

《JavaScript實現圖片合成下載》

《70個JavaScript知識點詳細總結(上)【實踐】》

《70個JavaScript知識點詳細總結(下)【實踐】》

《開源了一個 JavaScript 版敏感詞過濾庫》

《送你 43 道 JavaScript 面試題》

《3個很棒的小眾JavaScript庫,你值得擁有》

《手把手教你深入鞏固JavaScript知識體系【思維導圖】》

《推薦7個很棒的JavaScript產品步驟引導庫》

《Echa哥教你徹底弄懂 JavaScript 執行機制》

《一個合格的中級前端工程師需要掌握的 28 個 JavaScript 技巧》

《深入解析高頻項目中運用到的知識點匯總【JS篇】》

《JavaScript 工具函數大全【新】》

《從JavaScript中看設計模式(總結)》

《身份證號碼的正則表達式及驗證詳解(JavaScript,Regex)》

《瀏覽器中實現JavaScript計時器的4種創新方式》

《Three.js 動效方案》

《手把手教你常用的59個JS類方法》

《127個常用的JS代碼片段,每段代碼花30秒就能看懂-【上】》

《深入淺出講解 js 深拷貝 vs 淺拷貝》

《手把手教你JS開發H5遊戲【消滅星星】》

《深入淺出講解JS中this/apply/call/bind巧妙用法【實踐】》

《手把手教你全方位解讀JS中this真正含義【實踐】》

《書到用時方恨少,一大波JS開發工具函數來了》

《乾貨滿滿!如何優雅簡潔地實現時鐘翻牌器(支持JS/Vue/React)》

《手把手教你JS 異步編程六種方案【實踐】》

《讓你減少加班的15條高效JS技巧知識點匯總【實踐】》

《手把手教你JS開發H5遊戲【黃金礦工】》

《手把手教你JS實現監控瀏覽器上下左右滾動》

《JS 經典實例知識點整理匯總【實踐】》

《2.6萬字JS乾貨分享,帶你領略前端魅力【基礎篇】》

《2.6萬字JS乾貨分享,帶你領略前端魅力【實踐篇】》

《簡單幾步讓你的 JS 寫得更漂亮》

《恭喜你獲得治療JS this的詳細藥方》

《談談前端關於文件上傳下載那些事【實踐】》

《面試中教你繞過關於 JavaScript 作用域的 5 個坑》

《Jquery插件(常用的插件庫)》

《【JS】如何防止重複發送ajax請求》

《JavaScript+Canvas實現自定義畫板》

《Continuation 在 JS 中的應用「前端篇」》

作者:徐小夕

轉發連結:https://mp.weixin.qq.com/s/2Bk8lkRCNyaTWYtIB0oYVg

關鍵字: