常見的正則使用備忘

緣起

正則表達式就是一把利器,拿出來的時候每每無往不利, 可是咱們經常卻將之束之高閣, 只因她不是那麼漂亮,不那麼讓人印象深入.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。

關鍵字

  • match

語法: 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]
["原字符串",            "截取出來的字符串",  "位置編碼",  "輸入",                   "組"]
*/
  • exec

語法:reg.exec(str)
檢索字符串中指定的值。匹配成功返回一個數組,匹配失敗返回null。

  • test

直接用來判斷是否正確, 比較簡單

  • compile

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']

matchexec對比

類似點:
match和exec在匹配成功時返回的都是數組,在沒有匹配上時返回的都是null

不一樣點
1.全局匹配
當不使用全局匹配的時候,matchexec基本一致

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);

clipboard.png

當使用全局匹配的時候,matchexec返回數據不一樣
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);

clipboard.png

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);

clipboard.png

全局匹配分組時,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);

clipboard.png

replace使用

正則表達式構造函數: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

參考文檔

相關文章
相關標籤/搜索