【JavaScript】正則表示式--非貪婪模式擷取任意字串的筆記
阿新 • • 發佈:2019-02-13
場景
要將下面的字串擷取兩個{title:***,url:***}
來。
12345 | <script>{title:'RegExp 物件參考手冊',url:'http://sodino.com/regexp.asp'},{title:'w3cSchool script', url:'http://www.w3cSchool.com'},{}</script> |
正則表示式一
12345678910 | var string = '<script>' +"{title:'RegExp 物件參考手冊',url:'http://sodino.com/regexp.asp'}," +"{title:'w3cSchool script', url:'http://www.w3cSchool.com'}," |
這個毫無疑問是全匹配,即輸出為第一個{
到最後一個}
之間的全部內容:
12 | D:\github\niVoVin>node test.js[ '{title:\'RegExp 物件參考手冊\',url:\'http://sodino.com/regexp.asp\'},{title:\'w3cSchool script\', url:\'http://www.w3cSchool.com\'},{}' ] |
正則表示式二
書上說在表示式的後面加上?
就是非貪婪模式了。即n?
匹配包含零個或一個n
的字串。
那麼目前想的是隻匹配一個}
,那麼將表示式修改為如下:
1 | var reg = /\{.+\}?/g; |
執行一下程式碼,發現輸出是竟然是第一個{
到字串結尾:
12 | D:\github\niVoVin>node test.js[ '{title:\'RegExp 物件參考手冊\',url:\'http://sodino.com/regexp.asp\'},{title:\'w3cSchool script\', url:\'http://www.w3cSchool.com\'},{}</script>' ] |
那?
的作用竟然是忽略}
陷入了深深的疑惑……
排查問題
當表示式一和表示式二對比時,直覺告訴你是由於引入?
才導致的錯誤。
那麼需要來驗證下。
1 | var reg = /script>?/g; |
更換表示式,驗證是否?
一樣會忽略掉>
???
執行輸出得到:
12 | D:\github\niVoVin>node test.js[ 'script>', 'script', 'script>' ] |
所以?
並不是忽略的作用。所以直覺不對。
再看錶達式二的輸出結果,結果是將第一個{
後的內容全部輸出,那就是說表示式二的結果是由於一直在匹配.+
(任意數量的任意字元,除了換行和結束符),而沒有匹配到截止符}?
的原因。
而由於}?
處於可匹配可不匹配的情況,直譯器優先選擇不匹配,導致截止符}
是無效的。
參考連結正則基礎之——貪婪與非貪婪模式
那麼解決辦法就變為截止符}
不可設定為非貪婪,這樣才有截止作用,而對應的是對.+
(任意字元)執行非貪婪匹配,儘可能少的匹配{
與}
之間的內容。
正則表示式三
1 | var reg = /\{.+?\}/g; |
輸出結果:
123 | D:\github\niVoVin>node test.js[ '{title:\'RegExp 物件參考手冊\',url:\'http://sodino.com/regexp.asp\'}', '{title:\'w3cSchool script\', url:\'http://www.w3cSchool.com\'}' ] |
很圓滿。
由於.+
中+
表示最少出現一次.
,所以第三行的空{}
並沒有被匹配成功。
結論
在表示式三中,.+
表達任意字串,}
是截止符。
當使用n+
n*
n?
擷取任意字串時,如果待擷取內容包括任意字串,則非貪婪模式應儘可能少的匹配任中間的任意字串,而非儘可能少的匹配截止符。