您當前位置: 南順網絡>> 官方資訊>> 建站知識

淺談正則速記法的(de)技巧

元字符

/a/中的(de)a就是一(yī)個元字符,一(yī)個元字符匹配一(yī)個實體字符,這裏的(de)“a”沒有特殊含義,就匹配一(yī)個英文a

/\d/就匹配0到9的(de)所有數字,如(rú)果兩個連寫/\d\d/就可(kě)以匹配10到99的(de)所有數字

/./可(kě)以匹配任何字符

集合

假如(rú)有一(yī)串字符串'0123456789',我隻想匹配其中的(de)'3','6','9',這時可(kě)以放在集合中/[369]/

執行後會發現隻有3被匹配到,是因為(wèi)集合中不管寫多少東西都代表一(yī)個元字符,集合也是一(yī)種元字符
你可(kě)能見過這樣都集合/[0-9a-zA-Z_]/它代表匹配所有數字,字母和(hé)下劃線,它與元字符/\w/的(de)效果是一(yī)樣的(de),集合更靈活\w更方便

排除型集合

/[^0-9]/除了數字都匹配(我喜歡叫它否定集合)

或(多選)

假設我有一(yī)大堆書單,我希望從中匹配出naroto和(hé)one piece,那麽可(kě)以這樣寫/naroto|one pice/ 豎線代表或,a或b,你也可(kě)以寫多個a|b|c|d,你當然可(kě)以寫出0|1|2...|9來匹配所有數字。但要注意和(hé)集合的(de)區别,集合是一(yī)個元字符,不能匹配單詞,|兩邊可(kě)以是多個元字符

分組

我現在有一(yī)堆文件,我希望匹配出後綴是.css和(hé).less的(de)文件,你可(kě)以很自(zì)然的(de)寫出/.css|.less/這樣的(de)代碼。其實還有一(yī)個簡便寫法/.(c|le)ss/,分組可(kě)以将若幹個元字符放在同一(yī)個作用域中做(zuò)處理(lǐ),通過分組我們可(kě)以寫出更簡練的(de)代碼

分組還有一(yī)個特殊的(de)用法,思考如(rú)何匹配'asd_asd_asd_asd_asd'這種字符串?

答案是/(asd)(_\1)+/,\1是個非常特殊的(de)元字符,代表重複使用第一(yī)個分組的(de)匹配結果,\2就代表第二個,以此類推,+加号表示重複一(yī)到多次(這個後面會講),需要注意的(de)是計數從1開始,\0代表另外的(de)意思(請看文檔)

量詞

一(yī)長(cháng)串字符中我隻想匹配連續的(de)數字,但/\d/隻會匹配一(yī)個,這時候可(kě)以使用量詞/\d{n,}/,n寫幾就是幾到多,比如(rú){1,}就是1到多。{n}這種寫法表示n個相連,匹配2333可(kě)以寫成/23{3}/

還有幾個簡寫的(de)量詞

  • +代表1到多,等于{1,}

  • *代表0到多,等于{0,}

  • ?代表0或1個,等于{0,1}

貪婪模式和(hé)非貪婪模式

量詞有個尴尬的(de)地(dì)方,比如(rú)用/.*a/去(qù)匹配 '123a123a',本來希望得到'123a',實際卻得到'123a123a'。這是因為(wèi)任何字符都滿足/./加上量詞會導緻從頭匹配到尾,但因為(wèi)我們還有其他元字符,所以這時正則引擎會回溯,将已經匹配的(de)結果從後往前一(yī)個個拿出來,與剩下的(de)元字符相匹配。
這種模式叫貪婪模式,它可(kě)能會産生預期之外的(de)結果和(hé)不必要的(de)性能浪費

解決方案是使用非貪婪模式,在量詞後面加?問号可(kě)以得到最小結果,現在使用/.*?a/去(qù)匹配就可(kě)以得到'123a'了。任何量詞後都可(kě)以使用非貪婪模式

環視(shì)

x(?=y)這個功能有很多種翻譯,比如(rú)零寬斷言,我個人感覺比較準确的(de)是“正向肯定環視(shì)”
x(?!y)正向否定環視(shì)

x代表元字符,y也代表元字符,x(?=y)的(de)意思是緊接着y的(de)x,比如(rú) '-1a--2b-',使用/\d(?=a)/去(qù)匹配,會得到1;/\d(?!a)/去(qù)匹配,會得到2。

這功能怎麽用?舉個例子(zǐ),有一(yī)段字符串'a(123)b',我隻想要括号內(nèi)的(de)內(nèi)容,但不想要括号
我需要匹配到右括号左邊的(de)位置,那麽我可(kě)以寫成/(?=\))/(注意括号需要轉義),我不想要左括号/[^(]/,我不關心括号內(nèi)的(de)內(nèi)容/.*/,這時組合三個正則就變成了/[^(].*(?=\))/

實際上這個功能匹配的(de)是位置,從匹配到的(de)位置開始找元字符,所以你如(rú)果在環視(shì)後面加量詞是沒用的(de)

其他

^和(hé)$也是匹配位置的(de)元字符,分别是匹配開頭和(hé)結尾,比如(rú)我們想匹配文件結尾是.js的(de)文件可(kě)以寫成/.js$/。匹配http開頭的(de)鏈接可(kě)以寫成/^http:\/\//

還有一(yī)些特殊的(de)\u[\b]\0等,需要你自(zì)己看文檔

标識符

g:一(yī)個正則隻會匹配一(yī)次,如(rú)果加上g标識符就會全局匹配, /\d/g,這個正則是不管兩個數字之間隔了什麽,都會将所有數字匹配出來

i:不區分大小寫/^http:\/\//i就會匹配http://和(hé)HTTP://

核心概念就這麽多,其他內(nèi)容請詳細查看文檔

你以為(wèi)這就結束了?其實還有後續哒!

我要繼續說環視(shì)

還有個神奇的(de)逆向環視(shì)沒有講x(?<=y) ,因為(wèi)這是18年(nián)才進正式标準的(de)功能,雖然它可(kě)能比js年(nián)齡大,但js就是不支持你怕不怕!

前面那個/[^(].*(?=\))/可(kě)以改成/(?<=y).*(?=\))/

正則最大但坑就是,讓新手産生正則無所不能的(de)想法,一(yī)個複雜字符串處理(lǐ)總以為(wèi)可(kě)以通過一(yī)個神奇的(de)正則來搞定。

正則不是萬能的(de)!

還是之前的(de)例子(zǐ),給字符串'a(1\(2(3)'讓你取括号內(nèi)的(de)內(nèi)容請問你怎麽取?首先應該弄清需求,如(rú)果正則過于難寫,可(kě)以用js的(de)字符串處理(lǐ)函數輔助正則,分部操作。另外正則的(de)性能并不高(gāo),不是說很複雜的(de)操作寫成一(yī)行正則性能就比其他方式快了,沒有測試就沒有發言權

正則理(lǐ)論上是有極限的(de),舉個例子(zǐ),有字符串1xxxyyyy2讓你取{n}個x和(hé){m}個y,n和(hé)m是不确定個數,寫成x{1,}y{1,}是沒問題的(de),但如(rú)果要求是x{n}y{n}就不行了,比如(rú)一(yī)個字符串有3個x,你就要取3個y,有4個x,你就要取4個y,單靠正則就無法完成了。

正則難,難在門檻高(gāo),門檻高(gāo)在難記,之所以難記,其實還是因為(wèi)反人類的(de)符号讓你下意識的(de)排斥它。熟悉正則,正式正則,學(xué)會正則,會給你帶來超乎想象的(de)便利!

以上就是本文的(de)全部內(nèi)容,希望對大家的(de)學(xué)習有所幫助


編輯:--ns868