好吧,正則表達式,我從來沒記過。以前要用的時候都是網上Copy一下的。這裡還是扯一下吧,以後要是有要用到的正則表達式那麼就收集到這個帖子里。(儘管我認為不會,因為我根本就不是一個專業的前端,我只是來划下水的\(^o^)/)應用範圍:正則表達式主要應用於對字元串中的信息實現查找,替換和提取操作。可處理...
好吧,正則表達式,我從來沒記過。以前要用的時候都是網上Copy一下的。
這裡還是扯一下吧,以後要是有要用到的正則表達式那麼就收集到這個帖子里。(儘管我認為不會,因為我根本就不是一個專業的前端,我只是來划下水的\(^o^)/)
應用範圍:正則表達式主要應用於對字元串中的信息實現查找,替換和提取操作。
可處理正則表達式的方法有6個:
regexp.exec,regexp.test,string.match,string.replace,string.search和string.split
應用原因:在JS中,正則表達式相對於等效的字元串處理來說,有著顯著的性能優勢。
缺點:正如大部分人所看到的,這個東西有的時候光是看起來就很複雜和難懂。起碼你讓我這種菜去維護一個正則表達式我在網上Copy不到,一般都會用非正則表達式的方式去處理,美其名曰:代碼可讀性!
JS中正則表達式必需寫在一行中,空白需要特別註意。
下麵上一段代碼:
var myRegExp=/^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/; var url="http://www.ora.com:8041/goodparts?q#fragment"; var result=myRegExp.exec(url);
看到上面這段代碼你知道什麼意思嗎,絕大多數人不知道,知道的人也要看半天。這就是為什麼大家都不願意寫這玩意。好了,這章就這樣吧,大家散了吧。
即使如此,我還是自己要寫下去,因為他實現的效果是這樣的:
result的結果是下麵這個數組:
["http://www.ora.com:8041/goodparts?q#fragment", "http", "//", "www.ora.com", "8041", "goodparts", "q", "fragment"]
這就是我為什麼繼續寫下去的原因所在。
好吧,讓我們一起學學這蛋疼又犀利的語法吧:
- ^ 表示字元串以下麵匹配的方式開始
- (?:([A-Za-z]+):)? 這個是套著捕獲分組1的非捕獲分組,必須後面跟著一個冒號才匹配(記住這裡的冒號才匹配是由後面那個冒號決定的),匹配一個協議名,也就是http。
- (?:) 表示一個非捕獲型分組
- 尾碼? 表示這個分組是可選的,他表示重覆0次或者一次。就比如你輸入的url為www.baidu.com,不帶協議名也是可以匹配的。
- (...) 表示一個捕獲型分組。一個捕獲型分組會複製它所匹配的文本,並將其放在result數組裡。每個捕獲分組都會被指定一個編號。第一個捕獲分組的編號是1,所以result[1]表示它。result[0]就是原字元串。
- [...] 表示一個字元類。A-Za-z其實很好理解,就是26個大寫字母和26個小寫字母。-代表範圍。
- 尾碼+ 表示這個字元類會被匹配一次或者多次。
- 後面那個: 它表示匹配的字元串必須後面跟著一個冒號
- (?:) 表示一個非捕獲型分組
- (\/{0,3}) 這個是捕獲分組2,這個因數匹配的是兩個左斜杠
- \/ 表示的就是一個/,可以理解為\n一樣的轉義字元。
- {0,3} 表示/這個東西會被匹配0到3次
- ([0-9.\-A-Za-z]+) 這個是捕獲分組3,匹配一個www.baidu.com之類的東西,由一個或多個字母和數字,以及 . 和 - 兩個字元組成。也就是說你的網址是www.baidu.....----com---也是正確的
- (?::(\d+)? 這個是套著捕獲分組4的非捕獲分組,匹配的是埠號。也就是以:開頭的數字。同事將這個數字捕獲後放入結果數組
- \d 表示的是一個數字字元,[0-9]也可以實現一樣的效果
- (?:\/([^?#]*))? 這又是一個套著捕獲分組5的非捕獲分組,它捕獲了goodparts
- (?:\/(...))? 匹配以左斜杠/開頭的字串0到1次
- [^?#] 匹配非?和#的所有字元,^表示非的意思
- 尾碼* 表示被匹配0次或者多次,和尾碼+差不多,不過+是從1開始,
- (?:\?([^#]*))? 同上吧,類似的,自己應該可以理解了吧
- (?:#(.*))? 大致同上,
- . 會匹配除行結束符以外的所有字元
- $ 表示字元串以上面那些匹配的方式結束
老實說,我照著書看完,又把這些話歸納總結出來,然後我就一直在想一個問題。
到底我是什麼時候覺得正則表達式很難的呢?
是我還超級菜,並且還不愛學的時候。看什麼都覺得難,再加上人也浮躁,不想沉下心來去學,所以形成了一個這樣的印象。如今看來真是簡單至極。
我會告訴你我基本上就從來沒有自己寫過正則表達式嗎,我只會copy。
但是我在剛剛一個小時的學習中,我覺得我可以了,而且我能立馬寫出一段很6的正則表達式,無論多長,只需要把每個捕獲分組換一行寫就行了,然後貼到代碼里時再合成一行。
突然的感悟:程式員只是需要一個安靜的心和學習的興趣。
我不會告訴你我是邊看書邊寫博客的,好了,接下來我們繼續吧。
無論如何,即時我現在明白了正則表達式不難,但是仍然還是把正則表達式寫得越簡單越好。
那麼下麵來寫一個匹配數字的正則表達式吧
var myRegExp=/^-?\d+(?:\.\d*)?(?:e[+\-])?\d+)?$/i; var url="-1.3e-3"; var result=myRegExp.test(url);//result為true
這上面的正則表達式的最後的 i 表示匹配字元串時忽略大小寫。那麼讓我們擴展一下:
- 以i結尾:表示忽略字元串大小寫,都會匹配
- 以g結尾: 表示全局的(匹配多次)。對於test方法不建議使用g,string的search方法會自動忽略g標識。
- 以m結尾:多行($和^能匹配行結束符)
創建正則表達式的方式:
- 最簡單的,就像我上面那麼玩的
-
var myRegExp=/^-?\d+$/i
-
- 另外一種是使用RegExp構造器。Reg構造器適用於,必須在運行時動態生成正則表達式的情形。
-
var myRegExp=new RegExp("\"(?:\\\\.|[^\\\\\\\"])*\"",'g');
- RegExp的屬性
- global:如果標識g被使用,值為true。
- ignoreCase:如果標識i被使用,值為true。
- lastIndex:下一次exec匹配開始的索引。初始值為0.
- multiline:如果標識m被使用,值為true
- source:正則表達式源碼文本
- 用正則表達式字面量創造的RegExp對象,共用同一個單例。(我自己測了一下發現並非如此,所以這句話真實性有待確認)
關於構成正則表達式的元素
- 分支:用|表示,兩個正則表達式可以用|並起來成為一個,如果字元串匹配由|分隔的兩個正則表達式任意一個,那麼這個選擇匹配。
- 正則表達式匹配量詞,簡單來講就是匹配多少次
- {3,6}表示會匹配3到6次
- * 等同於{0,}
- + 等同於{1,}
- ? 等同於{0,1}
- ASCII碼特殊字元的匹配寫法:
-
[!-\/:-@\[-'{-~]
非常難看,且難懂,所以我的正則表達式啊,唉~~~
-
- 正則表達式分組類型
- 捕獲型:()
- 非捕獲型:(?:)進行簡單的匹配,並不會捕獲所匹配的文本。會有微弱的性能優勢。
- 向前正向匹配:(?=) 作者說這個特性和下麵這個特性並非好的特性,所以,我已經決定開始忘掉了。
- 向後負向匹配:(?!)
- 需要加轉義字元的字元:\ / [ ] ( ) ? + - * | . ^ s
- 同時一些有趣的轉義字元
- \f 換頁符
- \n 換行符
- \r 回車符
- \t 製表符即tab
- \u 允許指定一個Unicode字元來表示一個16進位的常量
- \d 等同於[0-9],\D正好相反,等同於[^0-9]
- \s 等同於[\f\n\r\t\u000B\u0020\u00A0\u2028\u2029].這是一個Unicode空白字元的不完全子集,\S正好相反
- \w 等同於[0-9A-Z_a-z],\W正好相反,\W希望表示的是字母類但是它通常很難起作用。
- 所以一個更簡單的字母類是[A-Za-z\u00C0-\u1FFF\u2800-\uFFFD],它包括所有Unicode字母和其他非字母字元。Unicode比這大的多,但是太龐大而低效了。所以用這個簡單的就好
- \b 被指定為一個字邊界標識,方便對文本的字邊界進行匹配。然而他會用\w去找邊界,所以對多語言來說這是個不好的特性。
- \1 \2 \3分別值的第1、2、3個分組所捕獲的文本的一個引用
- 所以用此正則表達式可以用來搜索文本中是否存在重覆的單詞隔著幾個空白字元挨在一起的情況:
var doubledWord=/([A-Za-z\u00C0-\u1FFF\u2800-\uFFFD]+)\s+\1/gi;
- 所以用此正則表達式可以用來搜索文本中是否存在重覆的單詞隔著幾個空白字元挨在一起的情況: