正則表達式就是一把利器,拿出來的時候每每無往不利, 可是咱們經常卻將之束之高閣, 只因她不是那麼漂亮,不那麼讓人印象深入.html
經常使用元字符正則表達式
標識 | 說明 |
---|---|
. | 匹配除換行符之外的任意字符 |
\w | 匹配字母或數字或下劃線或漢字, 若僅限英文等價於[a-z0-9A-Z_] |
\s | 匹配任意的空白符,包括空格,製表符(Tab),換行符,中文全角空格等 |
\d | 匹配數字 |
\b | 匹配單詞的開始或結束 |
^ | 匹配字符串的開始 |
$ | 匹配字符串的結束 |
反義字符數組
標識 | 說明 |
---|---|
\W | 匹配任意不是字母,數字,下劃線,漢字的字符 |
\S | 匹配任意不是空白符的字符 |
\D | 匹配任意非數字的字符 |
\B | 匹配不是單詞開頭或結束的位置 |
[^x] | 匹配除了x之外的任意字符 |
[^aeiou] | 匹配除了aeiou這幾個字母之外的任意字符 |
重複函數
標識 | 說明 |
---|---|
* | 重複零次或更屢次 |
+ | 重複一次或更屢次 |
? | 重複零次或一次 |
{n} | 重複n次 |
{n,} | 重複n次或更屢次 |
{n,m} | 重複n到m次 |
分支條件 | 測試
爲了解決相似下面的問題 \(?0\d{2}[) -]?\d{8}
匹配相似(010)88886666,或022-22334455,或02912345678等電話號碼. 首先是一個轉義字符(,它能出現0次或1次(?),而後是一個0,後面跟着2個數字(d{2}),而後是)或-或空格中的一個,它出現1次或不出現(?),最後是8個數字(d{8})編碼
分支條件就是將可以涉及到的全部狀況都經過|
列舉出來, 至關於程序代碼的||
, 若是前部分知足條件, 則不會在判斷後部分. url
0\d{2}-\d{8}|0\d{3}-\d{7}
這個表達式能匹配兩種以連字號分隔的電話號碼:一種是三位區號,8位本地號(如010-12345678),一種是4位區號,7位本地號(0376-2233445)。\(0\d{2}\)[- ]?\d{8}|0\d{2}[- ]?\d{8}
匹配3位區號的電話號碼,其中區號能夠用小括號括起來,也能夠不用,區號與本地號間能夠用連字號或空格間隔,也能夠沒有間隔spa
分組
使用()
將知足條件的表達式隔離出來做爲獨立的一部分
如: (\d{1,3}\.){3}\d{1,3}
((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)
將2[0-4]\d|25[0-5]|[01]?\d\d?
看成一個總體便可 prototype
一些示例code
\ba\w*\b
匹配以字母a開頭的單詞——先是某個單詞開始處(b),而後是字母a,而後是任意數量的字母或數字(\w*)
,最後是單詞結束處(\b)
。
\d+
匹配1個或更多連續的數字。這裏的+是和相似的元字符,不一樣的是匹配重複任意次(多是0次),而+則匹配重複1次或更屢次。
\b\w{6}\b
匹配恰好6個字符的單詞
零寬斷言
查找在某些內容(但並不包括這些內容)以前或以後的東西,也就是說它們像\b
,^
,$
那樣用於指定一個位置,這個位置應該知足必定的條件(即斷言).
標識 | 說明 |
---|---|
(?=exp) | 匹配exp前面的位置 |
(?<=exp) | 匹配exp後面的位置 |
(?!exp) | 匹配後面跟的不是exp的位置 |
(?<!exp) | 匹配前面不是exp的位置 |
(?=exp)
也叫零寬度正預測先行斷言
,它斷言自身出現的位置的後面能匹配表達式exp。好比\b\w+(?=ing\b)
,匹配以ing結尾的單詞的前面部分(除了ing之外的部分),如查找I'm singing while you're dancing.時,它會匹配sing和danc。
(?<=exp)
也叫零寬度正回顧後發斷言,它斷言自身出現的位置的前面能匹配表達式exp。好比(?<=\bre)\w+\b
會匹配以re開頭的單詞的後半部分(除了re之外的部分),例如在查找reading a book時,它匹配ading。
(?<=\s)\d+(?=\s)
,同時使用了兩種斷言, 匹配以空白符間隔的數字(再次強調,不包括這些空白符)。
爲了解決:\b\w*q[^u]\w*\b
匹配包含後面不是字母u的字母q的單詞。可是若是多作測試(或者你思惟足夠敏銳,直接就觀察出來了),你會發現,若是q出如今單詞的結尾的話,像Iraq,Benq
,這個表達式就會出錯。這是由於[^u]
總要匹配一個字符,因此若是q是單詞的最後一個字符的話,後面的[^u]
將會匹配q後面的單詞分隔符(多是空格,或者是句號或其它的什麼),後面的w*b將會匹配下一個單詞,因而\b\w*q[^u]\w*\b
就能匹配整個Iraq fighting
。負向零寬斷言能解決這樣的問題,由於它只匹配一個位置,並不消費任何字符。如今,咱們能夠這樣來解決這個問題:\b\w*q(?!u)\w*\b
。
(?!exp)
也叫零寬度負預測先行斷言
, 斷言此位置的後面不能匹配表達式exp, \d{3}(?!\d)
匹配三位數字,並且這三位數字的後面不能是數字;\b((?!abc)\w)+\b
匹配不包含連續字符串abc的單詞。
(?<!exp)
也叫零寬度負回顧後發斷言
, 斷言此位置的前面不能匹配表達式exp:(?<![a-z])d{7}匹配前面不是小寫字母的七位數字
一個更復雜的例子:(?<=<(\w+)>).*(?=<\/\1>)
匹配不包含屬性的簡單HTML標籤內裏的內容。(?<=<(\w+)>)
指定了這樣的前綴:被尖括號括起來的單詞(好比多是),而後是.*(任意的字符串),最後是一個後綴(?=<\/\1>)
。注意後綴裏的\/
,它用到了前面提過的字符轉義;\1
則是一個反向引用,引用的正是捕獲的第一組,前面的(w+)匹配的內容,這樣若是前綴其實是的話,後綴就是了。整個表達式匹配的是和之間的內容(再次提醒,不包括前綴和後綴自己)。
貪婪與懶惰
貪婪: 儘量匹配最長的字符串
懶惰: 匹配知足條件的第一個字符串
懶惰限定符
標識 | 說明 |
---|---|
*? | 重複任意次,但儘量少重複 |
+? | 重複1次或更屢次,但儘量少重複 |
?? | 重複0次或1次,但儘量少重複 |
{n,m}? | 重複n到m次,但儘量少重複 |
{n,}? | 重複n次以上,但儘量少重複 |
a.*?b
匹配最短的,以a開始,以b結束的字符串。若是把它應用於aabab
的話,它會匹配aab
(第一到第三個字符)和ab
(第四到第五個字符)
爲何第一個匹配是aab(第一到第三個字符)而不是ab(第二到第三個字符)?簡單地說,由於正則表達式有另外一條規則,比懶惰/貪婪規則的優先級更高:最早開始的匹配擁有最高的優先權——The match that begins earliest wins。
語法: str.match(reg)
, 參數可傳入字符串或者正則表達式.
關鍵注意正則表達式是否攜帶g
, 判斷實現全局匹配.
若是匹配成功, 返回匹配的值, 取返回數據的[0]
元素; 若是失敗,返回null
var str = "aaabbbcccdddeeefff"; strResult = str.match(/aaa(\S*)fff/); console.log(strResult); /* 返回一個類數組, 可以使用Array.prototype.slice.call(strResult)轉化爲真正的數組 ["aaabbbcccdddeeefff", "bbbcccdddeee", index: 0, input: "aaabbbcccdddeeefff", groups: undefined] ["原字符串", "截取出來的字符串", "位置編碼", "輸入", "組"] */
語法:reg.exec(str)
檢索字符串中指定的值。匹配成功返回一個數組,匹配失敗返回null。
直接用來判斷是否正確, 比較簡單
compile() 方法用於改變 RegExp。
compile() 既能夠改變檢索模式,也能夠添加或刪除第二個參數。
var reg=/hello/; console.log(reg.exec('hellojs'));//['hello'] reg.compile('Hello'); console.log(reg.exec('hellojs'));//null reg.compile('Hello','i'); console.log(reg.exec('hellojs'));//['hello']
match
和exec
對比類似點:
match和exec在匹配成功時返回的都是數組,在沒有匹配上時返回的都是null
不一樣點
1.全局匹配
當不使用全局匹配的時候,match
和exec
基本一致
var s = "aaa bbb ccc"; var reg = /\b\w+\b/;//沒有g var rs_match = s.match(reg); var rs_exec = reg.exec(s); console.log("match:",rs_match); console.log("exec:",rs_exec);
當使用全局匹配的時候,match
和exec
返回數據不一樣match
直接以數組的形式返回匹配的全部數據exec
返回的數據的格式和未使用全局匹配一致, 可是是逐個匹配目標字符串. 返回的index
下標可以獲取第幾個匹配的初始位置.
var s = "aaa bbb ccc"; var reg = /\b\w+\b/g;//有g var rs_match1 = s.match(reg); var rs_match2 = s.match(reg); var rs_exec1 = reg.exec(s); var rs_exec2 = reg.exec(s); console.log("match1:",rs_match1); console.log("match2:",rs_match1); console.log("exec1:",rs_exec1); console.log("exec2:",rs_exec2);
2.分組
無全局匹配分組時,match和exec返回結果相同。
因爲正則表達式採用了括號分組,因此在返回匹配結果的同時,依次返回該結果的全部分組, 如上面示例str.match(/aaa(\S*)fff/)
返回結果, 類數組的第二個元素就是分組(()
中的數據)的元素.
var s = "aaa1 bbb2 ccc3"; var reg = /\b(\w+)(\d{1})\b/;//兩個分組,無g var rs_match1 = s.match(reg); var rs_match2 = s.match(reg); var rs_exec1 = reg.exec(s); var rs_exec2 = reg.exec(s); console.log("match1:",rs_match1); console.log("match2:",rs_match1); console.log("exec1:",rs_exec1); console.log("exec2:",rs_exec2);
全局匹配分組時,match和exec返回結果不一樣。
match會返回全部匹配到的結果;
exec會返回本次匹配到的結果,若表達式中出現分組,則會依次返回本次匹配的所有分組:
var s = "aaa1 bbb2 ccc3"; var reg = /\b(\w+)(\d{1})\b/g; var rs_match1 = s.match(reg); var rs_match2 = s.match(reg); var rs_exec1 = reg.exec(s); var rs_exec2 = reg.exec(s); var rs_exec3 = reg.exec(s); var rs_exec4 = reg.exec(s); console.log("match1:",rs_match1); console.log("match2:",rs_match1); console.log("exec1:",rs_exec1); console.log("exec2:",rs_exec2); console.log("exec3:",rs_exec3); console.log("exec4:",rs_exec4);
正則表達式構造函數:new RegExp("pattern"[,"flags"]);
正則表達式替換變量函數:stringObj.replace(RegExp, replace Text);
//下面的例子用來獲取url的兩個參數,並返回urlRewrite以前的真實Url var reg=new RegExp("(http://www.qidian.com/BookReader/)(\\d+),(\\d+).aspx","gmi"); var url="http://www.qidian.com/BookReader/1017141,20361055.aspx"; //方式一,最簡單經常使用的方式 var rep=url.replace(reg,"$1ShowBook.aspx?bookId=$2&chapterId=$3"); console.log(rep); // http://www.qidian.com/BookReader/ShowBook.aspx?bookId=1017141&chapterId=20361055 //方式二 ,採用固定參數的回調函數 var rep2=url.replace(reg,function(m,p1,p2,p3){ console.log('mmmm => ', m, p1,p2,p3) return p1+"ShowBook.aspx?bookId="+p3+"&chapterId="+p3 }); alert(rep2); //方式三,採用非固定參數的回調函數 var rep3=url.replace(reg,function(){var args=arguments; return args[1]+"ShowBook.aspx?bookId="+args[2]+"&chapterId="+args[3];}); alert(rep3); //方法四 //方式四和方法三很相似, 除了返回替換後的字符串外,還能夠單獨獲取參數 var bookId; var chapterId; function capText() { var args=arguments; bookId=args[2]; chapterId=args[3]; return args[1]+"ShowBook.aspx?bookId="+args[2]+"&chapterId="+args[3]; } var rep4=url.replace(reg,capText); alert(rep4); alert(bookId); alert(chapterId); //使用test方法獲取分組 var reg3=new RegExp("(http://www.qidian.com/BookReader/)(\\d+),(\\d+).aspx","gmi"); reg3.test("http://www.qidian.com/BookReader/1017141,20361055.aspx"); //獲取三個分組 console.log(RegExp.$0) console.log(RegExp.$1); // http://www.qidian.com/BookReader/ console.log(RegExp.$2); // 1017141 console.log(RegExp.$3); // 20361055