正則表達小結與小知識點集錦

jopen 8年前發布 | 8K 次閱讀

背景介紹

這幾天,剛來公司,導師安排點任務增加些功能,以便熟悉了開發環境。接到的任務中,有一個環節需要處理一個業務的json數據,具有多級嵌套,我要做的是讓使用者可以修改其中的"userName"。

有兩個思路

  • 利用正則表達式進行匹配替代

  • 利用遍歷修改鍵值

當然,看到兩個思路的高下,在大部分情況下都是可以直接得出結論的,正則肯定是優于遍歷的。

正則表達式小結

創建方式

  • 直接量語法
    /pattern/attributes

  • 創建RegEx對象的語法
    new RegExp(pattern,attributes)

語法屬性說明:pattern我們寫的正則表達式的規則,而attributes則是規則的修飾符,g為全局匹配,i為區分大小寫的匹配,m為多行匹配。

語法

括號

用于查找某個范圍內的字符

  [acg] //匹配acg任一項即可
  [^acg]//匹配acg之外的任何一個字符
  [a-z] //匹配a到z  26個小寫字母的任何一個即可
  [A-Z] //匹配A到Z 26個大寫字母的任何一個即可
  (red|blue|green) //匹配red或者blue或者green任何一個即可

元字符

擁有特殊含義的字符

.    //查找單個字符,除了換行以及行結束符
\w   //查找單詞字符
\W   //查找非單詞字符
\d   //查找數字
\D   //查找非數字
\xxx //查找八進制書xxx規定的字符

量詞

描述規則執行的次數要求以及位置要求

n+ //匹配任何包含至少一個n的字符串
n? //匹配任何包含零個或者一個n的字符串
n* //匹配包含任一個n的字符串
n{x,y}  //匹配包含x到y次n的字符串
^n  //匹配開頭含有n的字符串
n$  //匹配結尾有n的字符串
?=n //匹配任何其后緊跟指定字符串n的字符串
?!n //匹配任何其后沒有緊跟字符串n的字符串
\b  //匹配一個字邊界,即字與空格間的位置
\B  //非字邊界匹配

方法

RegExp的方法

  • compile 編譯正則表達式

  • exec 執行正則表達式,并返回找到的值與位置

  • test 檢測是否真的含有符合正則表達式的字符串,返回布爾值

String對象的方法

  • search 檢索與正則表達式相匹配的值

  • match 找到一個或者多個正則表達式的匹配

  • replace 替換與正則表達式相匹配的子串

  • split 把字符串分割為字符串數組


小知識點集錦

子表達式

一個正則表達式可分為許多子表達式
例子:利用子表達式可以將通用資源指示符 (URI) 分解為其組件。假定您想將下面的 URI 分解為協議(ftp、http 等等)、域地址和頁/路徑

var test = http://www.w3cschool.cc:80/html/html-tutorial.html;

/\w+:\/\/[^/:]+:\d*?[^# ]*/.exec(test)  
     //只可以匹配到鏈接
//輸出結果
["http://www.w3cschool.cc:80/html/html-tutorial.html",
 index: 0, input: "http://www.w3cschool.cc:80/html/html-tutorial.html"]      

/(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/.exec(test)  
    //不僅可以匹配到鏈接,還可以把鏈接分為各個部分輸出
//輸出結果
["http://www.w3cschool.cc:80/html/html-tutorial.html", 
"http", "www.w3cschool.cc", ":80", "/html/html-tutorial.html", 
index: 0, input: "http://www.w3cschool.cc:80/html/html-tutorial.html"] 

貪婪的量詞

? * + 三者都是貪婪的

因為他們會盡可能多的匹配字符串,只要在他們后面再加一個?就可以實現非貪婪或者最小匹配
實例如下

<h1>Hello world!<h1>
//下面的表達式匹配從 < 到關閉h1標記的 >之間的所有內容
/<.*>/
//如果你只需要匹配開始的h1標記,下面的非貪婪表達式只匹配<h1>
/<.*?>/

圓括號的副作用消除

圓括號有一個副作用,那就是相關匹配會被緩存,此時可在在圓括號中加上?:在寫正則表達式

/(?:<.*>)/

String.match(/<.+>/g) 與 RegExp.exec(string)的區別

不得不說這個是讓我迷惑的很久的坑

  • String.match(/<.+>/g)
    這個是字符串方法,返回數組,包括與正則表達式匹配的第一個或者所有字符串,是否返回多個值由修飾符g決定(不返回子表達式的匹配結果)

  • RegExp.exec(string)
    這個是正則表達式對象的特有方法,返回一個數組。數組包含:正則表達式匹配到的第一個字符串,各個子字符串匹配到的字符串,另外還有兩個鍵值index與input,分別輸出匹配到的字符串的第一個字符的位置與被檢測的字符串。

所以想要輸出()的子字符串匹配的字符串必須要用exec,(?:)同樣也只要在用exec的時候才能檢測到效果。

RegExp.exec(string) 總結

介紹

這個可以取到各個子表示的結果,并且可以返回對應的index值。擁有非常大的想象空間。比如我想獲
"userName":"test"的值使用match,我們需要先匹配整個鍵值對,再對這個鍵值對進行處理才能取到鍵值。而使用exec,通過子表達式,我們則直接可以獲取到鍵值。

當然,exec有個蛋疼的地方是只能取到第一個匹配的字符串,也就是說修飾符g設置沒設置對他來說都一樣。

那我們如何用exec來全局匹配呢?

首先,我們來了解一下exec的一個特殊地方

當exec執行全局匹配模式時,exec的行為就略有變化。這時它會定義lastIndex屬性,以指定下一次執行匹配時開始檢索字符串的位置。在找到了與表達式相匹配的文本之后,exec方法將把正則表達式的lastIndex屬性設置為下一次匹配執行的第一個字符的位置。也就是說,可以通過反復地調用exec方法來遍歷字符串中的所有匹配文本。當exec再也找不到匹配的文本時,將返回null,并且把屬性lastIndex重置為0。

var s = "Hello world Hello world";  // 測試使用的字符串直接量

var r = /Hello/g;    // 匹配模式 一定要加上修飾符g

while((a = r.exec(s)) != null){ // 循環執行匹配操作

  console.log(a);
  console.log(r.lastIndex);
  /* 顯示每次匹配操作時返回的結果數組信息*/
}

測試結果

["Hello", index: 0, input: "Hello world Hello world Hello world"]
5
["Hello", index: 12, input: "Hello world Hello world Hello world"]
17

bingo,完成全局匹配。注意正則表達式,一定要加上修飾符g。要不然lastindex并不會改變,
循環會始終為真,不斷執行。

結語

這篇小結,也是花了好幾個小時去查資料,測試最后寫出來的,之前也看過許多正則的資料,卻始終停留在看看,認為知道了,每次想起來的時候,又都忘了,前幾天,用的時候就手忙腳亂的邊查資料邊coding。終于認識到了自己的學習方式給自己帶來的深刻問題。

其實,走上技術的路,時間也不短了。
但確實在技術學習的路上,有許多觀點,隨著時間與自身情況的變化,并未及時的更新。

曾經,在決定未來走向的時候,為了海量的獲取信息來看到更遠的未來,從而找尋一條能夠堅定走下路。讀書與閱讀的時候,采用快速閱讀的方式,不去細細咀嚼,只覺得看過一遍,迅速了解擴展視野,了解更多的東西就好。開始的時候,這種方式為我建立了認知,獲得了遠大于自身水平的視野。但是視野不曾有技術的支撐,只是一幢危樓而已。行之今日,這種學習方式暴露的問題,越來越大。后來,雖有意識,卻不曾有動力予以改正。

幸得近來被人指正,得以真正意識到問題的嚴重性。

非自己所研究的方向,有一定認識就好,用不著過度深入,采用快速閱讀的方式,自然是極好的。能夠快速建立認識。但是真正自己的研究方向,發散性閱讀才是更好的方式,對于每個點,都不僅僅局限于理解這一個點,能夠另行查閱許多相關的資料,這樣的方式,看一本書讀懂一本書,并擴展閱讀了許多相關的資料。這確實是更為行之有效的技術學習方式。而不像之前的方式,看似讀過,卻處處有漏洞,不曾真正的讀透一本書,希望臨到項目,臨到業務。再去真正實踐,去真正的掌握。是一種極為不靠譜的方式。

學習的方法的重要性,不亞于學習本身,也是值得我們去反思并改進的。

參考資料

正則表達式|菜鳥教程
W3Cschool正則表達式
使用exec增強正則表達式功能

來自: https://segmentfault.com/a/1190000004319104

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!