一、為什么需要學習正則表達式
正則表達式是一種應用廣,靈活度高的一種查找方式,目前在爬蟲爬取,對特定的內容的抓包,登錄的驗證等多個方面都用得上正則表達式,正是因為其極高的靈活度,所以也會給我們的使用帶來一定的麻煩,同時也提高了我們開發的復雜程度,復雜程度主要表現在語法上的不便記憶和應用層面上的易出錯,今天我們就來談談正則表達式在應用層面上常出現的錯誤
二、正則表達式常見坑與注意點
1、零寬斷言理解錯誤
零寬斷言匹配的相當於是一個位置,不是一個具體的內容
示例:
將字符串str="test.com"的.前面的替換為1,也就是str="1.com"
錯誤示范:
var str="test.com"; console.log(str); var reg=/(?=\.)*/gi; //var re=new RegExp(reg); str=str.replace(reg,"1"); console.log(str);
運行結果是:str="1t1e1s1t1.1c1o1m",我想此時你的心情一定是這樣的
從這個運行結果來看,就是在原來的字符串中的每個字符前面插入1,但是這個並不是我們所要求的,造成這樣的原因主要是位置弄錯了,現在把代碼改為如下所示:
var str="test.com"; console.log(str); var reg=/\w+(?=\.)/gi; //var re=new RegExp(reg); str=str.replace(reg,"1"); console.log(str);
這樣運行一下就得到了我們所要求的,這個位置我們其實是要求:零寬斷言+匹配類型+元字符+零寬斷言,錯誤示范中是零寬斷言+元字符這樣的一種組合,根本不符合語法的要求,所以錯誤。但是里面除了匹配類型是一定要存在的,其余的都可以按要求省去,也就是說不是必須的
2、后向調用理解錯誤
示例:
匹配字符串str="455 33"
錯誤示范
var str="455 33"; var test=/\b([1-4]\d{1,2})\s?\1\b/gi; console.log(test.test(str));
這個錯誤主要的原因是對后向調用的理解有誤,后向調用第n次使用時匹配第一次的完全相同的內容,但是不意味着在這里第二次引用前面分組的正則表達式,所以這里只匹配“455 455”這樣的字符串
對了這里里面的/g指的是全局匹配也就是在傳入中的全部內容進行搜索,如果不設置的話那么就返回第一個匹配的內容,/i也就是忽略大小寫的意思,除了這兩個外還有/m,表示多行匹配,什么是多行匹配呢?就是匹配換行符兩端的潛在匹配。影響正則中的^$符號
3、全局變量的導向錯誤
這個錯誤不知道怎么說,但就是挺奇葩的,知道的人麻煩再下面留言一下
示例:
將.號前面的內容替換為"t",字符串為"dd1.432"
錯誤示范:
var str="dd1.432"; var reg=/\w*?(?=\.)/gi; str=str.replace(reg,"t"); console.log(str);
這個時候原本你會以為正確運行但是,出現的效果確實“tt.432”,頓時你的內心一定是跟博主一樣有千萬只草泥馬在奔騰
但是最后的調試結果確實把最后面的g去掉,或者是修改為下面這樣
var str="dd1.432"; var reg=/^\w*?(?=\.)/gi; str=str.replace(reg,"t"); console.log(str);
4、對^ $理解上的錯誤
示例:
將上題修改為如下所示
錯誤示范:
var str="asdf dd1.432"; var reg=/^\w*?(?=\.)/gi; str=str.replace(reg,"t"); console.log(str);
^匹配的是傳入的字符串str的最開始的部分,$匹配的是str字符串最后的部分,如果是中間就不能使用這兩個限定,還好這個坑,博主不曾踩過
5、獲取某個DOM節點下面的內容
示例:
獲取標簽<ul>下面的內容,具體是str="<ul> leslie</ul><ul> 謝燦勇</ul>"
JavaScript代碼
var str="<ul> leslie</ul><ul> 謝燦勇</ul>"; var reg=/(?<=<ul>)[\s\S]*?(?=</ul>)/g; str=str.replace(reg,"t"); console.log(str);
運行的結果是:
這里面為什么會出現這樣的情況,相信此時你的內心也是奔潰的,猶如千萬只草泥馬呼嘯而過
經過了大量的試驗驗證,發現竟然是由於JavaScript中的正則表達式支持的相對比較少,所以也就沒有支持零寬度正回顧后發斷言[(?<=<ul>)],而且里面還存在另外的一個錯誤就是“/”是需要進行轉義操作的,但是這個時候我們發現要獲取<ul>位置后面的內容好像沒有方法可以實現了,經過了思考,我選擇了多次匹配來實現
6、多次匹配
接上面的問題繼續說下,我們所說的多次匹配其實就是第一次就只實現一部分,第二層次再實現一部分,這樣一直下去,直到完成。
我們第一次就只實現將</ul>去掉,然后將<ul>去掉,這樣就得到我們所要求的
var str="<ul> leslie </ul><ul> xiecanyong</ul>"; var reg=/<ul>[\s\S]*?(?=<\/ul>)/gi; str=str.match(reg); var reg1=/<ul>/i; for(var i=0,max=str.length;i<max;i++){ str=str.replace(reg1," "); console.log(str); }
第一次實現的代碼是這樣的,但是一運行卻發現只打印出leslie,這里主要的原因是,第一次就將leslie存入str變量中,然后第二次調用時,str=“leslie”,所以根本獲取不到<ul>,所以根本就是為空,所以也就只匹配到leslie,將代碼修改為如下就可以正常運行了
var str="<ul> leslie </ul><ul> xiecanyong</ul>"; var reg=/<ul>[\s\S]*?(?=<\/ul>)/gi; str=str.match(reg); var reg1=/<ul>/i; for(var i=0,max=str.length;i<max;i++){ str[i]=str[i].replace(reg1," "); console.log(str[i]); }
打印一下結果:
好的問題完成了,哈哈,內心如釋重負
7、多次匹配實現思路
其實在上面的內容中已經實現了兩種常見的多次匹配的思想,一種是獲取我們所要求的[str=str.match(reg)],另一種是將我們要除去的東西替換為空[ str[i]=str[i].replace(reg1," ")]所示
三、總結
通過這篇文章主要是希望大家能夠學習到一些在JavaScript中你可能會遇到的一些坑,以及一些問題的實現思路,如果在這里有什么地方說錯的,歡迎大家幫忙指正,在此不勝感激,如果你覺得這篇文章對你有幫助的話請為我點一個贊,你的點贊是我前進的動力。后續如果是大家有什么問題的話,也歡迎大家留言共同探討