摘要:先看一張來自于菜鳥教程的定義四種形式,加和不加有什么區別,區別就是捕獲元與非捕獲元,表現形式就是用方法去匹配,捕獲組會單純保存在一組變量中。捕獲元與非捕獲元搞懂了,那與啥區別呢,答案,兩個區別。
想讀懂世間所有的那些{{BANNED}}正則表達式?做夢,年紀輕輕,想啥呢,盡自己最大努力學就行
引子JS學了用了也快一兩年了,對象啥的找到了也會用了,繼承啥的也入門了,但看別人的框架代碼,總是會隨時卡殼,有一個重大的原因,就是那看不懂的一串串火星文字(正則表達式),學習嗎,就是查缺補漏,不怕你不懂,就怕你覺得自己全懂了。說正事之前,先推薦一款軟件:RegexBuddy,無論是做正則的測試還是過程的研究,都是一款利器。
知識匯總語法復習,重點三塊知識:
貪婪匹配(? 0=
特殊字符:^ $ . * + ? = ! : | / ( ) [ ] { }
,火星文,基本就是他們組成的,要想匹配字符的本意,字面量表達式在特殊字符前加單斜杠,用new聲明的需要加雙斜杠;
非捕獲元字符:?:,?=(正向預查),?!(負向預查);
回溯引用,前面的字符匹配基本都和他有關;
其他,什么字符邊界啊,括號啊,中括號啊,等等 ;
正則表達式解析原理:這個不算我等渣暫時能寫出來的,推薦一篇
層層遞進剖析 貪婪匹配先理解貪婪匹配,正則表達式的日常應用基本也就滿足了,在菜鳥教程的語法開篇就已經提的很詳細了,比如有一個regex:/Chapter[1-9]/,這個字符串我們只能匹配到Chapter1-Chapter9,也就是Chapter的一級標題,但我們想匹配到二級或者三級標題怎么辦,這里就用到了貪婪匹配,就是在目標字符串中最大化的匹配結果,將前面的regex:/Chapter[1-9]/改成/Chapter[1-9]+/,這樣我們就能匹配Chapter1,Chapter12,Chapter123,但如果我們將其改為/Chapter[1-9]?/,這個無論/Chapter后面輸入多少個數字,都只能最多匹配一個數字,這里就是Chapter1,但與最初的表達式不同的是,這個表達式也能匹配裸的Chapter,這就是所謂(X?),問號前面的X可出現0次或者1次,當我們將其改為/Chapter[1-9]星號(避開markdown語法)/,這個最后可以達到?和+共同的結果,也就是所謂的,x出現任意次數。上面這些我們也可以通過[n,m]即n= 與貪婪匹配成對的另一個叫懶惰匹配,在前面出現的所有貪婪匹配后面加上一個?,這樣整個表達式就成了懶惰匹配,可以理解為最小化匹配,比如/Chapter[1-9]+/匹配Chapter12345的結果是Chapter12345,但/Chapter[1-9]+?/匹配的結果就是Chapter1;/Chapter[1-9]{2,4}/匹配結過是Chapter1234,而/Chapter[1-9]{2,4}?/結過是Chapter1234,這就是所謂的最小化去匹配結果,取下限,通常稱為懶惰模式。 以前看到什么?:,?=,?!,用的少,也就沒留意,最近大面積災荒,經常看到,甚是恐懼,以至于前面在讀gulp里面碰見個regex表達式:/-[0-9a-f]{8,10}-?/(匹配app-7ef5d9ee29.css這一類表達式中的md5值),就一頭栽進去,"-?"到底又有什么特殊的含義,最后才發現,那TMD就是一個貪婪匹配,你個蠢貨,但確實搞不懂源碼作者在想啥,也許是我沒碰到app-7ef5d9ee29-any.css這樣的文件名,要不非得多加個"-?"干啥,讓我直往坑里跳。 從上面代碼運行的截圖可以看出區別一,也就是(?:pattern)的形式的捕獲元匹配的結果會保存在最終的結果中,而(?=pattern);區別二看的不是很明顯,這時我們需要依靠RegexBuddy,這個過程中到底發生了什么?看運行截圖,如果你夠仔細,你可以發現區別,第一次匹配到結果,開始第二次匹配時,?:是從字符索引3開始,而?=是從2開始,這就是前面所說的消耗字符與不消耗字符。
回到正題,先搞懂什么叫捕獲組,概括起來就是,用括號如‘(pattern)’這樣的形式,匹配滿足括號中的,就是一個捕獲組。先看一張來自于菜鳥教程的定義:
四種形式,加?和不加有什么區別,區別就是捕獲元與非捕獲元,表現形式就是用exec方法去匹配,捕獲組會單純保存在一組變量中。理論太枯燥,直接看例子,來源于JS高設page106,略有改動: var str ="mom and dad and baby";
var pattern = /mom( and dad( and baby))/; //捕獲元形式
var pat= /mom(?: and dad(?: and baby))/; //非捕獲元形式
var mat = pattern.exec(str);
var match = pat.exec(str);
console.log(mat);
console.log(match);
看著devtools打印的結果,是不是有點眉目,是的,匹配的結果雖一致,但捕獲組匹配時,將滿足捕獲元形式的單元多帶帶保存為一個匹配結果,而非捕獲元不多帶帶保存,只保存完整匹配結果。我們常見的Regexp.$1,$2其實就是對捕獲組結果的引用。
捕獲元與非捕獲元搞懂了,那(?:pattern)與(?=pattern)啥區別呢,答案,兩個區別。區別一:前者匹配的結果包含捕獲元,后者匹配的結果則不包含;區別二:前者匹配捕獲元時,消耗字符(索引),而后者不消耗。還是來看一個例子:var str ="ababa";
var pattern = /ab(?:a)/g;
var pat= /ab(?=a)/g;
var mat = pattern.exec(str);
var match = pat.exec(str);
console.log(mat);
console.log(match);
mat = pattern.exec(str); //全局模式,第二次匹配
match = pat.exec(str); //全局模式,第二次匹配
console.log(mat);
console.log(match);
好了,最后一個問題,整箱預查(?=pattern)與負向預查(?!pattern),其實從中文單純來理解負向預查,是會帶來歧義的。這里的負向其實單單就是正向預查的取反,即要匹配的字符不滿足捕獲的條件,才能匹配到結果。
如果文章有什么描述不正確或模糊的地方,還請及時指正。
好了,先就說這么多嘛,雖然是無業游民,那也應該有享受周末的權利吧,畢竟找工作的壓力那么大,還是要自我緩解一下,see you last week。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/84674.html
摘要:則是將作為一組,表示出現多次。如果沒有使用標示,則僅返回第一個完整匹配及其相關的捕獲組。構造函數的全局屬性到存儲了分組匹配的結果。 showImg(https://segmentfault.com/img/remote/1460000018749261?w=1362&h=781); 感謝 本文參考《正則表達式迷你書》 分組和分支結構 分組 括號可以提供分組的功能。/a+/, 標示a出現...
摘要:正則表達式語法字符與字符類特殊字符以上特殊字符要想使用字面值,必須使用進行轉義字符類包含在中的一個或者多個字符被稱為字符類,字符類在匹配時如果沒有指定量詞則只會匹配其中的一個。 1. 正則表達式語法 1.1 字符與字符類 1 特殊字符:.^$?+*{}| 以上特殊字符要想使用字面值,必須使用進行轉義 2 字符類 1. 包含在[]中的一個或者多個字符被稱為字符類,字符類在匹配時如果沒有指...
摘要:對于含有量詞正則表達式,量詞是貪婪模式,會優先選擇盡可能多的匹配修飾的字符,所以該表達式會優先選擇匹配一個字符,當匹配不到時再選擇不匹配字符。 正則表達式的語法 普通字符 字母、數字、漢字、下劃線以及一些沒有特殊定義的標點符號,都屬于普通字符,正則表達式中的普通字符匹配字符本身,如: var str = abced console.log(str.match(/a/)) // [a,...
摘要:非貪婪模式盡可能少的匹配所搜索的字符串,而默認的貪婪模式則盡可能多的匹配所搜索的字符串。 導讀 你有沒有在搜索文本的時候絞盡腦汁, 試了一個又一個表達式, 還是不行. 你有沒有在表單驗證的時候, 只是做做樣子(只要不為空就好), 然后燒香拜佛, 虔誠祈禱, 千萬不要出錯. 你有沒有在使用sed 和 grep 命令的時候, 感覺莫名其妙, 明明應該支持的元字符, 卻就是匹配不到. 甚至,...
閱讀 977·2021-11-22 09:34
閱讀 2161·2021-11-11 16:54
閱讀 2196·2021-09-27 14:00
閱讀 940·2019-08-30 15:55
閱讀 1525·2019-08-29 12:46
閱讀 599·2019-08-26 18:42
閱讀 639·2019-08-26 13:31
閱讀 3183·2019-08-26 11:52