文章原文:https://www.cnblogs.com/yalong/p/15183458.html
1.普通的問號符號
因為 ?
是特殊符號,所以如果想把 ?
當做正常的問號匹配,就需要加轉義 \?
示例
var regex = /123\?456/
var str = '123?456'
regex.test(str) // true
2.量詞
問號可以表示重復前面內容的0次或一次,也就是要么不出現,要么出現一次
示例
var regex = /1?23/
regex.test('123') // true
regex.test('1123') // true
regex.test('1234') // true
regex.test('121') // false
3.惰性模式匹配
量詞模式是貪婪模式,在量詞后面加上問號,就變成了惰性匹配
看如下量詞的表格
模式 | 說明 |
---|---|
{n,m} | 連續出現 n 到 m 次。貪婪模式 |
{n,} | 至少連續出現 n 次。貪婪模式 |
{n} | 連續出現 n 次。貪婪模式 |
? | 等價於 {0,1}。貪婪模式 |
+ | 等價於 {1,}。貪婪模式 |
* | 等價於 {0,}。貪婪模式 |
量詞后面加上問號后如下 | |
模式 | 說明 |
---- | ---- |
{n,m}? | 連續出現 n 到 m 次。惰性模式 |
{n,}? | 至少連續出現 n 次。惰性模式 |
{n}? | 連續出現 n 次。惰性模式 |
?? | 等價於 {0,1}?。惰性模式 |
+? | 等價於 {1,}?。惰性模式 |
*? | 等價於 {0,}?。惰性模式 |
貪婪模式 跟 惰性模式的區別
- 貪婪匹配是先看整個字符串是否匹配,如果不匹配,它會去掉字符串的最后一個字符,並再次嘗試,如果還不匹配,那么再去掉當前最后一個,直到發現匹配或不剩任何字符。
- 惰性匹配是從左側第一個字符開始向右匹配, 先看第一個字符是不是一個匹配, 如果不匹配就加入下一個字符再嘗式匹配, 直到發現匹配
4.非捕獲性分組
- 正常只使用括號就是捕獲模式,可以捕獲括號里的數據,保存在內存中,所以捕獲模式會占用更多內存
- 非捕獲模式,就是在里面的最前面加
?:
示例
RegExp 會保存分組里的數據, 如下所示
var regex = /(\d{4})-(\d{2})-(\d{2})/
regex.test('2011-11-12') // true
RegExp.$1 // "2011"
RegExp.$2 // "11"
RegExp.$3 // "12"
使用?:
的分組就是非捕獲模式,RegExp 不會保存該分組的數據,如下所示
var regex = /(?:\d{4})-(\d{2})-(?:\d{2})/
regex.test('2011-11-12') // true
RegExp.$1 // "11"
RegExp.$2 // ""
5.斷言
1.正先行斷言(前瞻)
(?=X)
2.負先行斷言(前瞻)
(?!X)
3.正后發斷言(后顧)
(?<=X)
4.負后發斷言(后顧)
(?<!X)
語法 | 說明 |
---|---|
(?=X ) | 正先行斷言。僅當子表達式 X 在 此位置的右側匹配時才繼續匹配。例如,/w+(?=/d) 與后跟數字的單詞匹配,而不與該數字匹配。此構造不會回溯 |
(?!X) | 負先行斷言。僅當子表達式 X 不在 此位置的右側匹配時才繼續匹配。例如,例如,/w+(?!/d) 與后不跟數字的單詞匹配,而不與該數字匹配 |
(?<=X) | 正后發斷言。僅當子表達式 X 在 此位置的左側匹配時才繼續匹配。例如,(?<=19)99 與跟在 19 后面的 99 的實例匹配。此構造不會回溯 |
(?<!X) | 負后發斷言。僅當子表達式 X 不在此位置的左側匹配時才繼續匹配。例如,(?<!19)99 與不跟在 19 后面的 99 的實例匹配 |
簡單來說,前瞻就是 看后面等於(?=), 后面不等於 (?!), 后顧就是 前面等於 (?<=), 前面不等於 (?<!)
比如 (?<!AA)eat(?=milk) 表示, eat 前面不能是AA, 后面必須是 milk
比如 (?<=AA)eat(?!milk) 表示 eat 前面必須是AA, 后面不能是milk
示例
let str1 = "VVeatmilk"
let str2 = "AAeatfood"
let patt1 = new RegExp("(?<!AA)eat(?=milk)");
let patt2 = new RegExp("(?<=AA)eat(?!milk)");
let result1 = patt1.test(str1);
let result2 = patt2.test(str2);
console.log(result1) // true
console.log(result2) // true
以(?=p) 和 (?!p)為例
(?=p)
,其中 p 是一個子模式,即 p 前面的位置,或者說,該位置后面的字符要匹配 p
比如 (?=l)
,表示 l
字符前面的位置,例如:
var result = "hello".replace(/(?=l)/g, '#');
console.log(result);
// => "he#l#lo"
而 (?!p) 就是 (?=p) 的反面意思,比如:
var result = "hello".replace(/(?!l)/g, '#');
console.log(result);
// => "#h#ell#o#"
(?<=p)
和 (?<!p)
同理