正則啊,就像一座燈塔,當你在字符串的海洋不知所措的時候,總能給你一點思路;正則啊,就像一臺驗鈔機,在你不知道用戶提交的鈔票真假的時候,總能幫你一眼識別;正則啊,就像一個手電筒,在你需要找什么玩意的時候,總能幫你get你要的東西...
―― 節選自 Stinson 同學的語文排比句練習《正則》
欣賞了一段文學節選后,我們正式來梳理一遍JS中的正則,本文的首要目的是,防止我經常忘記正則的一些用法,故梳理和寫下來加強熟練度和用作參考,次要目的是與君共勉,如有紕漏,請不吝賜教,良辰謝過。
本文既然取題為“一條龍”,就要對得起”龍”,故將包括正則原理、語法一覽、JS(ES5)中的正則、ES6對正則的擴展、實踐正則的思路,我盡量深入盡量淺出地去講這些東西(搞得好像真能深入淺出一樣的),如果你只想知道怎么應用,那么看第二、三、五部分,基本就能滿足你的需求了,如果想掌握JS中的正則的,那么還是委屈你跟著我的思路來吧,嘿嘿嘿!
一、原理概論
在一開始用正則的時候,就覺得神奇,計算機究竟是怎么根據一個正則表達式來匹配字符串的?直到后來我遇到了一本書叫《計算理論》,看到了正則、DFA、NFA的概念和相互間的聯系,才有一些恍然小悟的意思。
但如果真的要從原理上吃透正則表達式,那么恐怕最好的方式是:
1. 首先去找一本專門講正則的書去看看,O'REILLY的“動物總動員”系列里就有;
2. 再自己實現一個正則引擎。
而本文的重點在于JS中正則的應用,故原理僅作簡單介紹(因為我也沒寫過正則引擎,也不深入),一來大致“糊弄下”像我一樣的好奇寶寶們對正則原理的疑惑,二來知道一些原理方面基本的知識,對于理解語法和寫正則是大有裨益的。
1. 正則引擎
為什么正則能有效,因為有引擎,這和為什么JS能執行一樣,有JS引擎,所謂正則引擎,可以理解為根據你的正則表達式用算法去模擬一臺機器,這臺機器有很多狀態,通過讀取待測的字符串,在這些狀態間跳來跳去,如果最后停在了“終結狀態”(Happy Ending),那么就Say I Do,否則Say You Are a Good Man。如此將一個正則表達式轉換為一個可在有限的步數中計算出結果的機器,那么就實現了引擎。
正則的引擎大致可分為兩類:DFA和NFA
1. DFA (Deterministic finite automaton) 確定型有窮自動機
2. NFA (Non-deterministic finite automaton) 非確定型有窮自動機,大部分都是NFA
這里的“確定型”指,對于某個確定字符的輸入,這臺機器的狀態會確定地從a跳到b,“非確定型”指,對于某個確定字符的輸入,這臺機器可能有好幾種狀態的跳法;這里的“有窮”指,狀態是有限的,可以在有限的步數內確定某個字符串是被接受還是發好人卡的;這里的“自動機”,可以理解為,一旦這臺機器的規則設定完成,就可以自行判斷了,不要人看。
DFA引擎不需要進行回溯,所以匹配效率一般情況下要高,但是它并不支持捕獲組,于是也就不支持反向引用和$這種形式的引用,也不支持環視(Lookaround)、非貪婪模式等一些NFA引擎特有的特性。
如果想更詳細地了解正則、DFA、NFA,那么可以去看一下《計算理論》,然后你可以根據某個正則表達式自己畫出一臺自動機。
2. 知識儲備
這一小節對于你理解正則表達式很有用,尤其是明白什么是字符,什么是位置。
2.1 正則眼中的字符串――n個字符,n+1個位置
在上面的“笑聲”字符串中,一共有8個字符,這是你能看到的,還有9個位置,這是聰明的人才能看到的。為什么要有字符還要有位置呢?因為位置是可以被匹配的。
那么進一步我們再來理解“占有字符”和“零寬度”:
占有字符是互斥的,零寬度是非互斥的。也就是一個字符,同一時間只能由一個子表達式匹配,而一個位置,卻可以同時由多個零寬度的子表達式匹配。舉個栗子,比如/aa/是匹配不了a的,這個字符串中的a只能由正則的第一個a字符匹配,而不能同時由第二個a匹配(廢話);但是位置是可以多個匹配的,比如//b/ba/是可以匹配a的,雖然正則表達式里有2個表示單詞開頭位置的/b元字符,這兩個/b是可以同時匹配位置0(在這個例子中)的。
注意:我們說字符和位置是面向字符串說的,而說占有字符和零寬度是面向正則說的。
2.2 控制權和傳動
這兩個詞可能在搜一些博文或者資料的時候會遇到,這里做一個解釋先:
控制權是指哪一個正則子表達式(可能為一個普通字符、元字符或元字符序列組成)在匹配字符串,那么控制權就在哪。
傳動是指正則引擎的一種機制,傳動裝置將定位正則從字符串的哪里開始匹配。
正則表達式當開始匹配的時候,一般是由一個子表達式獲取控制權,從字符串中的某一個位置開始嘗試匹配,一個子表達式開始嘗試匹配的位置,是從前一子表達匹配成功的結束位置開始的。
舉一個栗子,read(?=ing)ing/sbook匹配reading book,我們把這個正則看成5個子表達式read、(?=ing)、ing、/s、book,當然你也可以吧read看做4個單獨字符的子表達式,只是我們這里為了方便這么看待。read從位置0開始匹配到位置4,后面的(?=ing)繼續從位置4開始匹配,發現位置4后面確實是ing,于是斷言匹配成功,也就是整一個(?=ing)就是匹配了位置4這一個位置而已(這里更能理解什么是零寬了吧),然后后面的ing再從位置4開始匹配到位置7,然后/s再從位置7匹配到位置8,最后的book從位置8匹配到位置12,整一個匹配完成。
3. 匹配之旅“淺”度游(可跳過)
說了那么多,我們把自己當做一個正則引擎,一步一步以最小的單位――“字符”和“位置”――去看一下正則匹配的過程,舉幾個栗子。
3.1 基本匹配
正則表達式:easy
源字符串:So easy
匹配過程:首先由正則表達式字符e取得控制權,從字符串的位置0開始匹配,遇到字符串字符‘S',匹配失敗,然后正則引擎向前傳動,從位置1開始嘗試,遇到字符串字符‘o',匹配失敗,繼續傳動,后面的空格自然也失敗,于是從位置3開始嘗試匹配,成功匹配字符串字符‘e',控制權交給正則表達式子表達式(這里也是一個字符)a,嘗試從上次匹配成功的結束位置4開始匹配,成功匹配字符串字符‘a',后面一直如此匹配到‘y',然后匹配完成,匹配結果為easy。
3.2 零寬匹配
正則:^(?=[aeiou])[a-z]+$源字符串:apple
首先這個正則表示:匹配這樣一個從頭到尾完整的字符串,這整一個字符串僅由小寫字母組成,并且以a、e、i、o、u這5個字母任一字母開頭。
匹配過程:首先正則的^(表示字符串開始的位置)獲取控制權,從位置0開始匹配,匹配成功,控制權交給(?=[aeiou]),這個子表達式要求該位置右邊必須是元音小寫字母中的一個,零寬子表達式相互間不互斥,所以從位置0開始嘗試匹配,右側是字符串的‘a',符合因此匹配成功,所以(?=[aeiou])匹配此處的位置0匹配成功,控制權交給[a-z]+,從位置0開始匹配,字符串‘apple'中的每個字符都匹配成功,匹配到字符串末尾,控制權交回正則的$,嘗試匹配字符串結束位置,成功,至此,整個匹配完成。
3.3 貪婪匹配和非貪婪匹配
正則1:{.*}正則2:{.*?}源字符串:{233}
這里有兩個正則,在限定符(語法會講什么是限定符)后面加?符號表示忽略優先量詞,也就是非貪婪匹配,這個栗子我剝得快一點。
首先開頭的{匹配,兩個正則都是一樣的表現。
正則1的.*為貪婪匹配,所以一直匹配余下字符串'233}',匹配到字符串結束位置,只是每次匹配,都記錄一個備選狀態,為了以后回溯,每次匹配有兩條路,選擇了匹配這條路,但記一下這里還可以有不匹配這條路,如果前面死胡同了,可以退回來,此時控制權交還給正則的},去匹配字符串結束位置,失敗,于是回溯,意思就是說前面的.*你吃的太多了,吐一個出來,于是控制權回給.*,吐出一個}(其實是用了前面記錄的備選狀態,嘗試不用.*去匹配'}'),控制權再給正則的},這次匹配就成功了。
正則2的.*?為非貪婪匹配,盡可能少地匹配,所以匹配'233}'的每一個字符的時候,都是嘗試不匹配,但是一但控制權交還給最后的}就發現出問題了,趕緊回溯乖乖匹配,于是每一個字符都如此,最終匹配成功。
云里霧里?這就對了!可以移步去下面推薦的博客看看:
想詳細了解貪婪和非貪婪匹配原理以及獲取更多正則相關原理,除了看書之外,推薦去一個CSDN的博客 雁過無痕-博客頻道 - CSDN.NET ,講解得很詳細和透徹
二、語法一覽
正則的語法相信許多人已經看過deerchao寫的30分鐘入門教程,我也是從那篇文字中入門的,deerchao從語法邏輯的角度以.NET正則的標準來講述了正則語法,而我想重新組織一遍,以便于應用的角度、以JS為宿主語言來重新梳理一遍語法,這將便于我們把語言描述翻譯成正則表達式。
下面這張一覽圖(可能需要放大),整理了常用的正則語法,并且將JS不支持的語法特性以紅色標注出來了(正文將不會描述這些不支持的特性),語法部分的詳細描述也將根據下面的圖,從上到下,從左到右的順序來梳理,盡量不 主站蜘蛛池模板: 日韩成人在线看 | 国产一二 | 欧美在线播放一区二区三区 | 精品不卡 | 日韩视频三区 | 国产精品一区二区三区免费 | 日本在线免费观看 | 日本精品一区二区在线观看 | 欧美久久视频 | 69久久夜色精品国产7777 | 91麻豆精品国产91久久久更新时间 | 福利在线播放 | 一区二区免费在线播放 | 国产欧美精品一区二区三区四区 | 亚洲免费网 | 一区二区在线播放视频 | 人人干人人干 | 国产精品爱久久久久久久 | 国产日韩视频在线播放 | 日韩精品在线一区二区 | 91原创视频在线观看 | 盗摄精品av一区二区三区 | 黄色免费影视 | 欧美日韩在线精品 | av黄色在线观看 | 国产真实精品久久二三区 | 中文字幕av亚洲精品一部二部 | av在线一区二区三区 | 九九色综合| 91国产精品| 欧美精品日韩 | 午夜精品久久久久久久久 | 亚洲国产日韩a在线播放性色 | 日韩欧美在线播放视频 | 亚洲免费资源 | 国产激情在线观看 | 欧美性一区二区三区 | 久久久久久久久久毛片 | 欧美 日韩 国产 一区 | 99re国产| 亚洲黄色成人网 |