說真的,不去正兒八經的學正則,對付通常的工做是沒啥問題的,雖然咱們可能會常常用到replace,但畢竟度娘能提供大多時候你想要的;可當我看一些框架的源碼,總會被裏面一長串一長串的正則給嚇到;以前一篇博客裏有關於簡單的爬蟲實踐,其實離達到我預期的效果就差一批正則(Nodejs,不同的爬蟲實踐);因此,通常的正則毫無壓力,非通常的狀況下的正則,使人望而生畏;簡直就是語言界的一朵小奇葩!html
正則其實就是用一串字符去描述一套規則,因此,首先得自個兒很清楚要實現的正則具有哪些規則,而後用一串字符組合搭配去描述它;如下正則,能力有限,暫不考慮性能問題,僅供參考;前端
指定一個子表達式,用小括號包括起來;node
參與結果的分組:結果保存在$1-$9中:瀏覽器
'abc-123'.replace(/(\w+)-(\d+)/,'$2-$1'); // '123-abc'
不參與結果的分組:(?:reg) reg參與匹配規則,匹配到的結果不參與分組的結果框架
var str1='abc123'; var str2='abc'; var reg=/\w+(?:\d+)?/; reg.test(str1); // true reg.test(str2); // true
反向引用:對相同的分組簡寫爲對第一個分組結果的引用性能
// 匹配h1-h6的標籤 var reg=/<h[1-6]>.*?<\/h[1-6]>/i; '<h1>hhhhh1111</h1>'.test(reg) // true '<h2>hhhhhaaaa</h5>'.test(reg) // true // 若是像這樣確實能夠匹配到通常的h1-h6, // 但其實它也會匹配<h1>....</h6>這種先後不對等的狀況, // 使用分組,反向引用就能避免這種狀況 var reg=/<h([1-6])>.*?<\/\1>/i; // \1便是對第一個分組([1-6])的引用 '<h1>hhhhh1111</h1>'.test(reg) // true '<h2>hhhhhaaaa</h5>'.test(reg) // false
貪婪模式與非貪婪模式隻影響用次數修飾的子表達式,貪婪模式在整個表達式匹配成功後會繼續向後儘量多的匹配,非貪婪模式在表達式首次匹配成功後即返回結果;?除了表示匹配0次或1次以外,還有在次數修飾的子表達式後面表示是否啓用貪婪模式;this
// 過濾html標籤 var str1='<b class="aa" data-value="1">abc</b><div class="a">cde</div>hf'; var reg=/<\/?\w+.*>/ig; // 貪婪模式 var reg1=/<\/?\w+.*?>/ig; // 非貪婪模式 str1.replace(reg,''); // hf str1.replace(reg1,''); // abccdehf // 能夠看到非貪婪模式下的結果纔是咱們過濾標籤後想要的結果
在JS裏只支持向前斷言,也就是向前查找;url
(?=reg) 零寬正向先行斷言 (?!reg) 零寬負向先行斷言
這兩種斷言裏的reg只做爲整個表達式的一個必要條件,而不返回匹配結果,一樣不能與分組弄混淆;通常小括號用來劃分一個子表達式,(?:reg)的reg匹配的結果不參與整個表達式結果的分組;斷言的reg只做爲一個必要條件,參與整個表達式匹配的判斷,匹配的內容卻不參與整個表達式匹配的結果;spa
向前查找即從斷言開始的位置的右邊開始匹配;code
var str='abc123cdef456...........'; // 匹配數字後面跟着字母的內容, //「跟着字母」僅做爲一個條件,這個條件匹配到的結果不參與整個表達式匹配的結果 str.match(/\d+(?=[a-z]+)/g); // 123 而不是 456 str.match(/\d+(?!\w+)/g); // 456
其餘基礎如:s S w W b B d D [0-9a-zA-Z_] 等基礎符號組合應該相對好理解,做爲很基礎的部分,必須牢記咯;
其實絕大多數人都用過正則,但我更相信大多數人用的正則都是度娘提供的,爲了真正的走近正則,而不僅是道聽途說,必須全面的過一遍,而且儘量的用到實際工做中,好比:驗證個url,過濾個標籤等,相信本身弄出來一串字符的話,確定別有一番意思;以下Url模塊,對於前端來講基本上是多餘的,由於瀏覽器有location;parse方法的做用在於對非location情形下的自定義url或可認爲是url的字符串進行解析;好比:用戶輸入一串url,首先驗證是否符合url規則,而後提取協議類型,提取域名等,這些就是location作不到的,並且對於簡單的爬蟲操做替換或補全url,該方法就派上用場了;
Url.parse(url);//返回一個object
若是不帶url參數,則默認爲location.href;這時返回的結果和location能取到的同樣;
若是帶上url,不管是否自定義的,都將從新用正則解析,並返回一個和location能獲取到的同樣的結果集,包括格式化後的query;
Url.normalize(url);//返回url
首先對接收的url去空白字符,嘗試將多個連續的/符合替換爲一個,將多個.去掉(../或./的狀況),至關於放寬url的限定規則;
Url.isAccessUrl(url);//返回true|false
驗證是否符合正確的url規範;
Url.query;//返回 object
取得url上的查詢參數,{name:value}格式,如:Url.query.id取得url上id=123的值即返回123;
var Url=function(loc){ var urlUtils=function(){ return { trim:function(url){ return url.replace(/^\s+|\s+$/,''); }, norProtocol:function(url){ if (!/https?\:\/\//i.test(url)) throw url+' http or https protocol needed !'; return url.replace(/(https?\:\/\/)\/+/,'$1'); }, getProtocol:function(url){ return this.norProtocol(url).match(/(https?\:\/\/)/)[1]; }, tryOnce:function(url){ return this.getProtocol(url)+ this.norProtocol(url).substring(this.getProtocol(url).length) .replace(/\.+(?=\/)/g,'') .replace(/\/+/g,'/'); }, normalize:function(url){ var nor=this.tryOnce(this.trim(url)); return nor.match(/https?\:\/\/(\w+(?:\.\w+)+)(\:\d{2,5})?$/)?nor+='/':nor; }, isAccessUrl:function(url){ return /https?\:\/\/(?:\w+(?:\.\w+)+|localhost)(?:\:\d{2,5})?\/\S*/i.test(this.normalize(url)); }, convertQs:function(qs){ var qs=qs||loc.search.substring(1); if(!qs) return null; var qsArr=qs.split(/&/),qsPar={}; for(var i=0;i<qsArr.length;i++){ if (qsArr[i]) { var nm=qsArr[i].split(/=/); qsPar[decodeURIComponent(nm[0])]=decodeURIComponent(nm[1]||''); } } return qsPar; } } }(); function parse(url){ var url=url||loc.href; var noredUrl=urlUtils.normalize(url); if (!urlUtils.isAccessUrl(url)) throw url+' is not access URI !'; var medUrl=noredUrl.match(/https?\:\/\/(\w+(?:\.\w+)+|localhost)(?:\:(\d{2,5}))?(\/(?:[^#?]+)?)(?:\?([^#]+))?(?:#{1}(.+))?/i); console.log(medUrl) return { href:medUrl[0], protocol:urlUtils.getProtocol(noredUrl).replace(/\/\//,''), query:urlUtils.convertQs(medUrl[4]), host:medUrl[1], port:medUrl[2]||'80', pathname:medUrl[3], search:medUrl[4]||null, hash:medUrl[5]||null }; } return { parse:parse, normalize:urlUtils.normalize, isAccessUrl:urlUtils.isAccessUrl, query:urlUtils.convertQs(null) //{name:value} } }(location); module.exports=Url; 如:console.log(Url.parse('http:////www.famanoder.com/../dsvdsk?ds=w3q&&cdsvds=00 '));
將獲得以下結果:
正則研究的不太深,該模塊不免會有BUG,或繁瑣的地方,我的認爲在實際工做中仍是有用武之地的,後續慢慢修復吧;
正則這朵小奇葩仍是挺有意思的,相信更加熟練後在之後的前端之路上會帶給我意想不到的收穫!
若是你已在路上,就勇敢的向前吧!
原文來自:花滿樓(http://www.famanoder.com/boke...)