摘要:近幾日對自己一直不太擅長的正則表達式做了一次全面的掃盲。量詞在正則中,通常要表示一個表達式匹配的數(shù)量,這個時候量詞就登場了。而正則默認(rèn)是貪婪模式的。正則會默認(rèn)對捕獲組分配組數(shù)。
近幾日對自己一直不太擅長的正則表達式做了一次全面的掃盲。心疼自己之余還是有一些收獲吧,在這里做一個比較零散的總結(jié),整理一些對理解正則比較有利的點。一、"?"
你沒有看錯,就是黑人問號中的問號,這個字符在正則里面算是一個入門中很容易被帶偏的點了。首先要知道什么是正則中的量詞。
在正則中,通常要表示一個表達式匹配的數(shù)量,這個時候量詞就登場了。
主要會使用以下幾個量詞
/(w)*/.exec(str) // 匹配任意次 /(w)+/.exec(str) // 匹配一次到多次 /(w)?/.exec(str) // 匹配零到一次(記住這里問號的用法!) /(w){2, 4}/.exec(str) // 匹配兩次到四次 /(w){2, }/.exec(str) // 匹配兩次以上
我們可以發(fā)現(xiàn),在這里"?"作為一個量詞來使用,表示匹配零到一次。
接下來要理解下一個概念:貪婪匹配
搜了一下wiki,貌似沒有相關(guān)的詞條,通俗的解釋,貪婪匹配模式下,會盡可能多地匹配滿足條件的字符。而正則默認(rèn)是貪婪模式的。
舉個例子。比如我要匹配"suuuuuuuuuuck"字符中的s和k中間的字符。并沒有什么問題。
let result = "suuuuuuuuuuck".match(/s(.*)k/)[1] // uuuuuuuuuuc
但是我現(xiàn)在要搞事情,要你在"suuuuuuuuuuck duck"字符串中匹配相同的字段,同樣的表達式會匹配到以下的結(jié)果,因為此時的正則是貪婪的,它一定會匹配到無法匹配的時候才休止。
// uuuuuuuuuuck duc
這時候就需要手動開啟非貪婪模式了
let result = "suuuuuuuuuuck duck".match(/s(.*?)k/)[1] // uuuuuuuuuuc
區(qū)別是在量詞后加了個問號,這時候該捕獲組就算是開啟了非貪婪模式了。
按照上面的理解,如果你是一個新手,肯定會有所疑惑,量詞(*)后面跟著一個量詞(?),這是什么鬼意思,這么反人類的?
其實,這里就涉及到"?"的第二個用法了,即當(dāng)它跟在一個量詞背后的時候,表示該表達式開啟了非貪婪模式,即對表達式盡可能少地匹配結(jié)果。所以,對應(yīng)的,配合量詞使用,會產(chǎn)生以下結(jié)果。
"*?": 可以匹配任意多次,但是盡量少匹配。
"+?": 至少必須匹配一次,但是盡量少匹配。
"{m, n}?": 至少必須匹配m次,最多只能匹配n次,但是盡量少匹配。
"{m, }?": 至少必須匹配m次,但是盡量少匹配。
思考題:所以,"??" 應(yīng)該如何匹配呢?二、捕獲組
正則匹配除了驗證一個字符串是否符合條件外,還可以從中提取我們所需要的信息。比如,我們得到了一個"新中國成立于1949-10-01"的字符串,作為一個愛國人士,我們要把這個年月日提取出來謹(jǐn)記于心。所以我寫了一個正則,獲得的結(jié)果如下
這里提取的操作就需要通過小括號進行捕獲。正則會默認(rèn)對捕獲組分配組數(shù)。
"新中國成立于1949-10-01".match(/(d{4})-(d{2})-(d{2})/) // ["1949-10-01", "1949", "10", "01", index: 6, input: "新中國成立于1949-10-01", groups: undefined]
我們也可以忽略某些分組"(?:exp)",這樣正則就不會為為其分配組數(shù)。
"新中國成立于1949-10-01".match(/(d{4})-(d{2})-(?:d{2})/) // ["1949-10-01", "1949", "10", index: 6, input: "新中國成立于1949-10-01", groups: undefined]
假如我們有一個疊詞判斷的需求,驗證一個詞語是不是"ABA"格式的,我們可以這么做
// 首先漢字的unicode范圍是u4e00-u9fa5 // 這里我們首先對第一個字符進行了捕獲,組數(shù)為1 // 然后我們后面通過"1"的方式去復(fù)用捕獲組,這樣就意味著匹配到了相同的字符,也就達到了限制的目的。 /([u4e00-u9fa5])[u4e00-u9fa5]1/.test("是不是") // 當(dāng)然是true
要記住下標(biāo)對人類來說還是挺麻煩的,可以說完全沒啥可讀性,當(dāng)然正則也提供了為分組命名的方式
"新中國成立于1949-10-01".match(/(?d{4})-(? d{2})-(? d{2})/) // 我們可以發(fā)現(xiàn),這時候捕獲組不僅擁有組數(shù),同時groups屬性不為空了。 // ["1949-10-01", "1949", "10", "01", index: 6, input: "新中國成立于1949-10-01", groups: {…}] // 展開groups 是這樣的 // {year: "1949", month: "10", date: "01"} /** 當(dāng)然命名捕獲組也是可以使用的 */ // (? exp) 命名捕獲組 // k 引用 // 還是疊詞的那個例子 /(? [u4e00-u9fa5])[u4e00-u9fa5]k /.test("是不是")
現(xiàn)在有一個需求,匹配出英文語句"I"m singing while you"re dancing"中所有帶有ing后綴的單詞(不包含ing)。要想拿到danc 和 sing,我們需要用到零寬斷言。三、零寬斷言
零寬斷言用于查找某些內(nèi)容之前或之后的東西,只指定一個位置,本身并不占據(jù)字符,這也是為什么我們稱之為零寬度
對于表達式表示肯定,我們稱之為正向,反之稱之為負(fù)向,(注意,這里的正負(fù)指的是對條件的肯定和否定,而不是匹配的方向。)
而對于匹配的方向而言,我們有另外一種稱呼,對向后匹配的稱之為預(yù)測先行,向前匹配的稱之為回顧后發(fā)
所以,對應(yīng)的四種組合分別是
(?=exp) 零寬度正預(yù)測先行斷言(斷言自身出現(xiàn)的位置后面能匹配exp)
(?!exp) 零寬度負(fù)預(yù)測先行斷言(斷言自身出現(xiàn)的位置后面不能匹配exp)
(?<=exp) 零寬度正回顧后發(fā)斷言(斷言自身出現(xiàn)的位置前面能匹配exp)
(?
目前的js引擎對回顧后發(fā)斷言的實現(xiàn)還不完全,就我所知在chrome能成功使用,但是在nodejs環(huán)境下是不識別的。
現(xiàn)在我們從引言中的例子來實踐一下
"I am singing while you"re dancing".match(/([a-zA-Z]+)(?=ing)/g) // 我們忽略前面不滿足的匹配,直到index = 4時,s為單詞邊界,滿足條件 // 而第一個捕獲組是貪婪的,他會首先匹配到整個singing,然后將掌控權(quán)交給(?=ing),singing不滿足匹配 "singinging" // 于是開始回溯到單詞 singin,繼續(xù)斷言, 匹配到的下一個字符為"g", 不滿足"singining", 又開始回溯到"singi"... // 直到回溯到"sing"時,斷言后面有一個ing,并且是一個單詞邊界,于是"singing"滿足條件,這時候我們的正則匹配到了第一個結(jié)果。 // 由于零寬斷言是不消費字符的,所以我們得到整個表達式匹配的第一個結(jié)果是"sing" // 于是引擎以同樣的方式向后面的位置查找,得到了danc // ["sing", "danc"]
我們現(xiàn)在看一下怎么使用負(fù)向斷言,假如我們有一個系統(tǒng),3月25號要進行維護,不能使用了,這時候有用戶要辦理業(yè)務(wù),選擇日期的時候我們要過濾3月25日這一天,所以產(chǎn)品經(jīng)理要你臨時加上一條規(guī)則限定。
選擇后日期輸出的格式是"yyyy-mm-dd",這時候我們可以這么寫正則
/(?!2018-03-25)(d{4})-(d{2})-(d{2})/.test("2018-03-11") // true 通過驗證 /(?!2018-03-25)(d{4})-(d{2})-(d{2})/.test("2018-03-25") // false
用(?<=exp) 找出 "beep name=wanglihong abcdefg"
"beep name=wanglihong abcdefg".match(/(?<=name=)(w+)/) // ["wanglihong", "wanglihong", index: 10, input: "beep name=wanglihong abcdefg", groups: undefined]
提取a標(biāo)簽的屬性的同時,通過(?
var template = "點擊跳轉(zhuǎn)" template.match(/(w+)=(?摸透了零寬斷言,正則的能力也就算上了一個臺階了,當(dāng)然還有平衡組這種操作,因為在js不支持,所以就暫時不討論了。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/93514.html
摘要:對前端來說,使用的場景不多,但是像微信端的對話系統(tǒng)的表情包,就使用到了一個特定的規(guī)則。我是一個前端,工作年了,現(xiàn)在失業(yè),想進入騰訊工作,這是我的聯(lián)系方式這個正則雖 我發(fā)現(xiàn)有個別字符被這個編輯器給刷掉了,但是灰色區(qū)域顯示正常,以灰色區(qū)域代碼為準(zhǔn) 什么玩意? 在我剛開始學(xué)習(xí)編程的時候,就聽過正則了,也聽說正則很牛逼,懂正則的更牛逼。但是苦于沒有人指點,也沒有使用正則的場景,自己看教程又懵逼...
摘要:正如我標(biāo)題所說,簡歷被拒。看了我簡歷之后說頭條競爭激烈,我背景不夠,點到為止。。三準(zhǔn)備面試其實從三月份投遞簡歷開始準(zhǔn)備面試到四月份收,也不過個月的時間,但這都是建立在我過去一年的積累啊。 本文是 無精瘋 同學(xué)投稿的面試經(jīng)歷 關(guān)注微信公眾號:進擊的java程序員K,即可獲取最新BAT面試資料一份 在此感謝 無精瘋 同學(xué)的分享 目錄: 印象中的頭條 面試背景 準(zhǔn)備面試 ...
摘要:正如我標(biāo)題所說,簡歷被拒。看了我簡歷之后說頭條競爭激烈,我背景不夠,點到為止。。三準(zhǔn)備面試其實從三月份投遞簡歷開始準(zhǔn)備面試到四月份收,也不過個月的時間,但這都是建立在我過去一年的積累啊。 本文是 無精瘋 同學(xué)投稿的面試經(jīng)歷 關(guān)注微信公眾號:進擊的java程序員K,即可獲取最新BAT面試資料一份 在此感謝 無精瘋 同學(xué)的分享目錄:印象中的頭條面試背景準(zhǔn)備面試頭條一面(Java+項目)頭條...
摘要:一般在做前后端分離的時候,前端服務(wù)器用的都是,可是公司項目是需要運行在上面的,所以綜合考慮之下用比較好一些,然而這方面的資料不如那么多,所以就想記錄一下這段時間遇到的坑,以防自己以后再遇到的時候忘記了,這樣我可以翻出來看看。 一般在做前后端分離的時候, 前端服務(wù)器用的都是nginx,可是公司項目是需要運行在windows server上面的,所以綜合考慮之下用IIS比較好一些,然而這方...
閱讀 1656·2019-08-30 15:55
閱讀 978·2019-08-30 15:44
閱讀 871·2019-08-30 10:48
閱讀 2043·2019-08-29 13:42
閱讀 3188·2019-08-29 11:16
閱讀 1263·2019-08-29 11:09
閱讀 2059·2019-08-26 11:46
閱讀 619·2019-08-26 11:44