出來混總是要還的-JS正則常用的有四種操作: 驗證、切分、提取、替換

ntscshen發表於2018-10-22

前言:能看到這篇隨筆的朋友肯定, 多多少少接觸過正則( 不過還記得多少, 只有"天"知道 ), 基礎語法知識我們先扔一邊, 先從實際程式設計入手去, 驗證瀏覽器中正則的四種常規操作: 驗證、切分、提取、替換

使用正則的目的就三個

  1. 表單校驗( 查詢字串中是否有匹配正則規則的字元 ) 如果滿足就 XX, 如果沒滿足就 OO
  2. 提取字串中的內容(分組) - 提取之後做後續操作(替換replace就是提取的後續操作)
  3. 切分 split

1. 驗證

驗證:查詢字串中是否有匹配正則規則的字元。 先來一道基礎題

Demo1 判斷一個字串中是否包含"hello" ( 判斷字串中是否包含某個字串 )

String物件上的方法

方法一: indexOf()

let str = "hello world!";
console.log(str.indexOf("hello") != -1); // true
// 不是正則, 但卻是解決當前題的一種方案,
// indexOf()方法返回撥用String物件中第一次出現的指定值的索引, 如果未找到該值, 則返回-1
複製程式碼

方法二: includes()

let str = "hello world!";
console.log(str.includes("hello")); // true
// includes() 方法用於判斷一個字串是否包含在另一個字串中, 根據情況返回true或false
複製程式碼

方法三: search()

let str = "hello world!";
console.log(str.search(/hello/) != -1);
// 只有一個引數, 並且是一個正規表示式物件, 如果傳入一個非正規表示式物件,
// 則會使用 new RegExp(obj)隱式地將其轉換為正規表示式物件
// 如果匹配成功, 則返回正規表示式在字串中首次匹配項的索引, 否則, 返回-1
複製程式碼

方法四: match()

let str = "hello world!";
console.log(!!str.match(/hello/g));
// 如果傳入一個非正規表示式物件, 則會隱式地使用new RegExp(obj)將其轉換為一個RegExp
// 返回值(陣列), 如果匹配到陣列第一項是匹配的完整字串, 之後項是用圓括號捕獲的結果, 如果沒有匹配到, 返回null
// 如果正規表示式包含g標誌, 則該方法返回一個Array, 它包含所有匹配的子字串而不是匹配物件
複製程式碼

RegExp 物件上的方法

方法五: test()

let str = "hello world!";
console.log(/hello/.test(str));
// 用來檢視正規表示式與指定的字串是否匹配, 返回true或false
// 想要知道一個模式是否存在於一個字串中, 可以使用test()或者search
複製程式碼

方法六: exec()

let str = "hello world!";
console.log(!!/hello/.exec(str));
// exec() 方法在一個指定字串中執行一個搜尋匹配, 返回一個結果陣列或null,
// 如果只是為了判斷是否匹配(true或false), 可以使用RegExp.test()方法, 或者String.search()方法
複製程式碼

驗證總結:

  1. 一個確認的( 精準匹配 )字元查詢是否被包含, 使用 String.indexOf() 和 String.includes()
  2. 一個有規則的( 模糊匹配 )字元查詢是否被包含, 使用 RegExp.test() 和 String.search()
  3. 查詢不推薦, 使用 String.match() 和 RegExp.exec()

切分

切分:所謂"切分", 就是把目標字串, 切分成一塊一塊的, 在 JS 中使用 split

Demo2 目標字串是"html,css,javascript", 按逗號切分

let regex = /,/;
let str = "html,css,javascript";
let str2 = "2018/10/18";
console.log(str.split(regex));
console.log(str2.split(/\//));
複製程式碼

split() 方法使用指定的分隔符字串將一個String物件分割成字串陣列, 以將字串分隔為子字串, 以確認每個拆分的位置

分隔符可以是一個字串或正規表示式

提取

提取:很多時候需要提取部分匹配的資料, 通常需要使用分組引用( 分組捕獲 )

Demo3 提取年月日

方法一: match()

let str = "2018-10-18";
let regex = /^(\d{4})\D(\d{2})\D(\d{2})$/;
console.log(str.match(regex));
複製程式碼

方法二: exec()

let str = "2018-10-18";
let regex = /^(\d{4})\D(\d{2})\D(\d{2})$/;
console.log(regex.exec(str));
複製程式碼

方法三: test()

let str = "2018-10-18";
let regex = /^(\d{4})\D(\d{2})\D(\d{2})$/;
regex.test(str);
console.log(RegExp.$1, RegExp.$2, RegExp.$3);
複製程式碼

方法四: search()

let str = "2018-10-18";
let regex = /^(\d{4})\D(\d{2})\D(\d{2})$/;
str.search(regex);
console.log(RegExp.$1, RegExp.$2, RegExp.$3);
複製程式碼

方法五: replace()

let str = "2018-10-18";
let regex = /^(\d{4})\D(\d{2})\D(\d{2})$/;
let date = [];
str.replace(regex, function(match, year, month, day) {
  date.push(year, month, day);
});
console.log(date);
複製程式碼

提取總結: 本質上是捕獲分組 推薦使用matchexec 其中, 最常用的是match

String.prototype.match(); 引數: 一個正規表示式物件, 如果傳入一個非正規表示式物件, 則會隱式地使用 new RegExp(obj) 將其轉換為一個 RegExp, 如果你為提供任何引數, 直接使用 match(), 那麼你會得到一個包含空字串的陣列[""]

返回值:如果字串匹配到了表示式, 會返回一個陣列, 陣列第一項是進行匹配完整的字串, 之後的項是用圓括號捕獲的結果, 如果沒有匹配到, 則返回 null

如果正規表示式不包含 g 標誌, 則 str.match() 會返回和 RegExp.exec() 相同的結果。而且返回的Array擁有一個額外的input屬性, 該屬性包含被解析的原始字串, 另外, 還擁有一個index屬性, 該屬性表示匹配結果在原字元中的索引

如果正規表示式包含 g 標誌, 則該方法返回一個Array, 它包含所有匹配的子字串而不是匹配物件, 捕獲組不會被返回( 即不返回 index 屬性和 input 屬性 )。如果沒有匹配到, 則返回null

RegExp.exec() 方法在一個指定字串中執行一個搜尋匹配, 返回一個結果陣列或 null

String.match()RegExp.exec() 的主要區別

  1. 所屬類不同
  2. g 有關
  3. exec 只會匹配第一個符合的字串( 意味著 g 對其不起作用 )和所有分組的反向引用, 雖然 g 對其不生效,但其使用 lastIndexwhile 迴圈, 可以達到 g 的目的, 這點比 match 強大
  4. match 返回的陣列內容, 跟正規表示式中是否帶 g 有關係( 如果帶 g, 包含的是所有匹配的子字串 ) 如果不帶 g == 預設的 exec

替換

使用正則的目的, 往往是匹配到對應的規則的字元, 下一步常常是替換^_^

正則處理中最強大的 API, 劃重點、劃重點、劃重點, 因為其常常被一些偽裝者, 假借替換之名, 做一些皮肉生意

Demo4 從 yyyy-mm-dd 替換成 yyyy/mm/dd

replace

let str = "2018-10-18";
let regex = /-/g;
console.log(str.replace(regex, "/"));
複製程式碼

String.replace(); 有兩種使用形式, 第二個引數時字串還是函式

一、當其為字串時如下字元有特殊含義 $1,$2 ... $99 匹配 1-99 個分組捕獲的文字

二、當其為函式時, 回撥函式的引數具體意義 match( 匹配內容 ), $1( 分組1 ), $2( 分組2 ), index( 索引 ), input( 原字元內容 )

總結

  1. 驗證一個字串( 精準匹配 )是否被包含, 使用 String.indexOf()String.includes()
  2. 驗證一個字串( 模糊匹配 )是否被包含, 使用 String.search()RegExp.test()
  3. 切分一段字串( 無論確認字元和規則字元 ), 使用 String.split(字串/正則)
  4. 提取分組捕獲資訊, 使用 String.match()RegExp.exec() 注意區分它們之間的區別 -> g
  5. 替換, 使用 String.replace(String/RegExp, string/function) 注意第二個引數的的規則資訊

傳送門 -> 正則基礎方法應用

參考

《Javascript 正規表示式迷你書》

相關文章