正規表示式在前端開發中,對於字串處理任務來說,絕對是一件可以祭出的大殺器。同時對於前端開發人員來說也是一項基本技能,但若只是停留在能看懂,知道去哪查的階段,那距離得心應手地運用差的可能不止一步兩步。
行業總習慣通過工作年限,來粗略估計一個工程師的能力與水平,因為隨著時間的延展總覺得會積累下些許經驗。但年限這種間接的衡量指標太因人而異,太難得到及時的正反饋。後來慢慢地發現,只有基於自己獨立地思考,總結並輸出才會感到真實的成長,就像竹子長一段就得生一個節。
一. 正則使用分類
正規表示式(後文簡稱為“正則”)可劃分出兩種使用方式:
通過正則字面量與通過RegExp建構函式建立出來的正則物件,在不考慮訪問正則物件屬性的情況下,是等價的。如果需訪問正則物件的屬性,需通過RegExp初始化正則例項。
-
正規表示式字面量
/正則匹配模式/[修飾符]
字串物件內建了一些與使用正規表示式相關的方法,這些方法的入參就是所需的正規表示式字面量- match : 返回一個陣列或者在未匹配到時返回null
- search : 返回匹配到的位置索引,或者在失敗時返回-1
- replace : 使用替換字串替換掉匹配到的子字串
- split : 一個使用正規表示式或者一個固定字串分隔一個字串,並將分隔後的子字串儲存到陣列中
-
RegExp構造的正規表示式物件
new RegExp("正則匹配模式"[, 修飾符])
通過正則建構函式例項化的正則物件,同樣也具有類似的方法- exec : 返回一個陣列或者在未匹配到時返回null
- test : 匹配到返回true否則false
二. 正則的使用(持續更新)
-
當匹配到時,
exec
和match
返回結果的不同-
字串的match方法,當正規表示式按照字面量傳參時,返回匹配到字串的陣列
// 字串的match方法 var str = "cdbbdbsbz" var ret1 = str.match(/d(b+)d/g) console.log(ret1) // ["dbbd"]
當傳參為正則物件時,返回值與exec方法相同。
-
正則物件的exec方法,返回從索引值處開始首次匹配到結果的字串陣列,陣列的第一個元素為結果字串,若匹配模式中存在括號,則括號中的子模式在本次匹配中得到的字串,依次排列在結果陣列中。與此同時,該陣列物件還附帶了一些相關的屬性。
// 正則物件的exec方法 var regExp = new RegExp(/d(b+)d/, `g`) var ret2 = regExp.exec(str) console.log(ret2) // ["dbbd", "bb", index: 1, input: "cdbbdbsbz", groups: undefined]
物件 屬性 描述 例子中對應的值 retArray 匹配到的字串,和所有被記住的字串 [“dbbd”, “bb”] index 本次匹配結果,開始的索引值 1 input 初始字串 “cdbbdbsbz” [0] 本次匹配到的字串 “dbbd” regExp lastIndex 下一個匹配的索引值 5 source 匹配模式的文字 “d(b+)d”
-
-
使用括號的子字串匹配(組匹配)
拿上例的匹配模式來看/d(b+)d/g
,括號中匹配到的子字串,會被記錄在陣列元素[1],…,[n]中,且儲存數量可以是無限的。除了通過js直接使用外,還可以這樣使用:var name = "John Tom" var newName = name.replace(/(w+)s(w+)/, "$2 $1") console.log(newName) // Tom John
-
正規表示式修飾符
- g:全域性搜尋
- i:不區分大小寫搜尋
-
m:多行搜尋,
^
和$
匹配的開始或結束輸入字串中的每一行,而非整個輸入字串 -
u:開啟Unicode模式,用來正確處理大於
uFFFF
的字元 -
y:粘連匹配,類似全域性搜尋,但不同是其要求在
lastIndex
的位置發現匹配,而g
是從lastIndex
處開始搜尋,也就是說粘連匹配y
模式中隱藏了頭部匹配的標誌^
。
-
具名組匹配
上面有討論過組匹配的概念和用法,通過陣列下標的方式使用總會帶來些許不便,所以在ES2018中引入了具名組匹配,允許為每一個組匹配指定一個名字,以方便閱讀和呼叫,來看例子:// 之前的組匹配 const RE_DATE = /(d{4})-(d{2})-(d{2})/; const matchObj = RE_DATE.exec(`1999-12-31`); const year = matchObj[1]; // 1999 const month = matchObj[2]; // 12 const day = matchObj[3]; // 31 // 使用具名組匹配 const RE_DATE = /(?<year>d{4})-(?<month>d{2})-(?<day>d{2})/; const matchObj = RE_DATE.exec(`1999-12-31`); const year = matchObj.groups.year; // 1999 const month = matchObj.groups.month; // 12 const day = matchObj.groups.day; // 31
三. 正則匹配模式
下表列出了在正規表示式中,可以利用的特殊字元的完整列表和描述
字元 | 含義 |
---|---|
/ |
1. 在非特殊字元前,表示特殊用途; 2. 在特殊字元前,轉義為字面量;3. 在new RegExp(“pattern”) 中需將 進行轉義。 |
^ |
匹配輸入的開始。若設定多行匹配,則也匹配換行符後緊跟的位置 |
$ |
匹配輸入的結束。若設定多行匹配,則也匹配換行符前的位置。 |
* |
匹配前一個表示式0次或多次。等價於 {0,} |
+ |
匹配前面一個表示式1次或者多次。等價於 {1,} |
? |
1. 匹配前面一個表示式0次或者1次。等價於 {0,1};2. 如果緊跟在任何量詞 *、 +、? 或 {} 的後面,將會使量詞變為非貪婪的(匹配儘量少的字元),和預設使用的貪婪模式(匹配儘可能多的字元)正好相反。 |
. |
匹配除換行符之外的任何單個字元 |
(x) |
匹配 x 並且記住匹配項 |
(?:x) |
匹配 x 但是不記住匹配項(非捕獲括號) |
x(?=y) |
匹配 x 僅僅當x 後面跟著y (正向肯定查詢) |
x(?!y) |
匹配 x 僅僅當x 後面不跟著y (正向否定查詢) |
{n} |
匹配了前面一個字元剛好發生了n次(n為正整數) |
{n,m} |
匹配前面的字元至少n次,最多m次 |
[xyz] |
表示字符集合,匹配方括號的中任意字元 |
[^xyz] |
表示一個反向字符集,匹配沒在方括號的中任意字元 |
[] |
匹配一個退格(U+0008) |
|
匹配一個詞的邊界 |
B |
匹配一個非單詞邊界 |
cX |
當X是處於A到Z之間的字元的時候,匹配字串中的一個控制符 |
d |
匹配一個數字,等價於[0-9] |
D |
匹配一個非數字字元,等價於[^0-9]
|
f |
匹配一個換頁符 |
|
匹配一個換行符 |
|
匹配一個回車符 |
s |
匹配一個空白字元,包括空格、製表符、換頁符和換行符 |
S |
匹配一個非空白字元 |
|
匹配一個水平製表符 |
v |
匹配一個垂直製表符 |
w |
匹配一個單字字元(字母、數字或者下劃線) |
W |
匹配一個非單字字元 |
|
它返回最後的第n個子捕獲匹配的子字串(捕獲的數目以左括號計數) |
|