正則表達(dá)式
正則表達(dá)式(Regular Expression)是計(jì)算機(jī)科學(xué)的一個(gè)概念。正則表達(dá)式使用單個(gè)字符串來描述、匹配一系列符合某個(gè)句法規(guī)則的字符串。在很多文本編輯器里,正則表達(dá)式通常被用來檢索、替換那些符合某個(gè)模式的文本。
創(chuàng)建
JavaScript通過內(nèi)置對象RegExp支持正則表達(dá)式,有兩種方式創(chuàng)建正則表達(dá)式對象,如果我們想匹配字符串中<%xxx%>兩個(gè)百分號分割的字符串可以這么寫
構(gòu)造函數(shù)(不常用)
var reg=new RegExp('<%[^%>]+%>','g');
字面量
var reg=/<%[^%>]%>/g; //兩個(gè)'//'中間內(nèi)容是正則表達(dá)式,第二個(gè)/后可以是i,g,m
最后的g代表全局,還有幾個(gè)修飾符
g:global,全文搜索,不添加的話搜索到第一個(gè)結(jié)果停止搜索
i:ingore case,忽略大小寫,默認(rèn)大小寫敏感
m:multiple lines,多行搜索
元字符
正則表達(dá)式讓人望而卻步以一個(gè)重要原因就是轉(zhuǎn)義字符太多了,組合非常多,但是正則表達(dá)式的元字符(在正則表達(dá)式中具有特殊意義的專用字符,可以用來規(guī)定其前導(dǎo)字符)并不多
( [ { \ ^ $ | ) ? * + .
并不是每個(gè)元字符都有特定的意義,在不同的組合中元字符有不同的意義,分類看一下
字符含義
\t水平制表符(tab)
\r回車符
\n換行符
\f換頁符
\v垂直制表符
\0空字符
字符類
var reg = /[a-z]/ig //中括號中代表一個(gè)字符
var reg2 = /[^a-z]/ig //[]中內(nèi)容取反,noneof? [^a-z]
范圍類
按照上面的說明如果希望匹配單個(gè)數(shù)字那么表達(dá)式是這樣的
//匹配一個(gè)字符,這個(gè)字符可以是0-9中的任意一個(gè)
var reg1 = /[0123456789]/
//匹配一個(gè)字符,這個(gè)字符可以是0-9中的任意一個(gè)
var reg2 = /[0-9]/
//匹配一個(gè)字符,這個(gè)字符可以是a-z中的任意一個(gè)
var reg3 = /[a-z]/
//匹配一個(gè)字符,這個(gè)字符可以是大寫字母、小寫字母、數(shù)字中的任意一個(gè)
var reg3 = /[a-zA-Z0-9]/
預(yù)定義類
字符等價(jià)類含義
.[^\r\n]除了回車符和換行符之外的所有字符
\d[0-9]數(shù)字字符
\D[^0-9]非數(shù)字字符
\s[\t\n\x0B\f\r]空白符
\S[^\t\n\x0B\f\r]非空白符
\w[a-zA-Z_0-9]單詞字符,字母、數(shù)字下劃線
\W[^a-zA-Z_0-9]非單詞字符
有了這些預(yù)定義類,寫一些正則就很方便了,比如我們希望匹配一個(gè)可以是 ab+數(shù)字+任意字符 的字符串,就可以這樣寫了 /ab\d./
var str = 'hello world 12345? \t? \r good \n nuo'
str.search('world') //6
str.match('world') //["world", index: 6, input: "hello world 12345
good ? nuo"]
str.match(/\d/) //["1", index: 12, input: "hello world 12345
good ? nuo"]? 只返回第一個(gè)值
str.match(/\d/g) //["1", "2", "3", "4", "5"]
str.match(/\w/g) //["h", "e", "l", "l", "o", "w", "o", "r", "l", "d", "1", "2", "3", "4", "5", "g", "o", "o", "d", "n", "u", "o"]? 全局搜索 返回所有
str.match(/\W/g) //[" ", " ", " ", " ", "? ", " ", " ", "
", " ", " ", "?", " "]
邊界
正則表達(dá)式還提供了幾個(gè)常用的邊界匹配字符
字符含義
^以xxx開頭
$以xxx結(jié)尾
\b單詞邊界
\B非單詞邊界
var str = 'hello1 world hello2 123456 \t \r jirengu \n ruoyu hello3'
str.match(/hello\d/g)? // ["hello1", "hello2", "hello3"]
str.match(/^hello\d/g)? // ["hello1"]
str.match(/hello\d$/g)? // ["hello3"]
var str2 = 'hello1 whello9orld hello2 12-hello8-3456 \t \r jirengu \n ruoyu hello3'
str2.match(/hello\d/g)? //["hello1", "hello9", "hello2", "hello8", "hello3"]
str2.match(/\bhello\d\b/g)? //["hello1", "hello2", "hello8", "hello3"]
//注意-也用于區(qū)分單詞邊界
題目:篩選符合條件的class-name
var str = 'header clearfix active header-fixed node'
str.match(/(^|\s)header($|\s)/g)? ? //["header "]
量詞
之前我們介紹的方法都是一一匹配的,如果我們希望匹配一個(gè)連續(xù)出現(xiàn)20次數(shù)字的字符串難道我們需要寫成這樣
\d\d\d\d...
為此正則表達(dá)式引入了一些量詞
字符含義
?出現(xiàn)零次或一次(最多出現(xiàn)一次)
+出現(xiàn)一次或多次(至少出現(xiàn)一次)
*出現(xiàn)零次或多次(任意次)
{n}出現(xiàn)n次
{n,m}出現(xiàn)n到m次
{n,}至少出現(xiàn)n次
var str = 'http://youtube.com'
var str2 = 'https://youtube.com'
var str3 = 'httpshttps://youtube.com'
str.match(/https?:\/\/.+/g)? ? //["http://youtube.com"]
str2.match(/https?:\/\/.+/g)? ? //["https://youtube.com"]
str2.match(/^(https?:)?\/\/.+/g)? ? //["https://youtube.com"]
str3.match(/(https){2}:\/\/.+/g)? ? //str3.match(/(https){2}:\/\/.+/g)
//匹配手機(jī)號
var num = '13888888888'
num.match(/^1[3578]\d{9}$/g)? //["13888888888"]
貪婪模式與非貪婪模式
量詞在默認(rèn)下是盡可能多的匹配的,也就是大家常說的貪婪模式
'123456789'.match(/\d{3,5}/g); //["12345", "6789"]
非貪婪模式和貪婪模式相反,可通過在代表數(shù)量的標(biāo)識符后放置'?'來開啟非貪婪模式
'123456789'.match(/\d{3,5}?/g); //["123", "456", "789"]
分組
有時(shí)候我們希望使用量詞的時(shí)候匹配多個(gè)字符,而不是像上面例子只是匹配一個(gè),比如希望匹配Byron出現(xiàn)20次的字符串,我們?nèi)绻麑懗?hunger{10} 的話匹配的是hunge+r出現(xiàn)10次
/hunger{10}/
怎么把hunger作為一個(gè)整體呢?使用()就可以達(dá)到此目的,我們稱為分組
/(hugner){10}/
或
var reg1 = /hello|world/
//等同于
var reg2 = /(hello)|(world)/
var str1 = 'helloworld'
str1.match(/hell(o|\s)world/)? // ["helloworld", "o", index: 0, input: "helloworld"]
str1.match(/hello|\sworld/)? ? //["hello", index: 0, input: "helloworld"]
前瞻
表達(dá)式含義
exp1(?=exp2)匹配后面是exp2的exp1
exp1(?!exp2)匹配后面不是exp2的exp1
例子
hunger(?=Byron)
(/good(?=Byron)/).exec('goodByron123'); //['good']
(/good(?=Byron)/).exec('goodCasper123'); //null
(/bad(?=Byron)/).exec('goodCasper123');//null
正則表達(dá)式——相關(guān)方法
RegExp.prototype.test(str)
方法用于測試字符串參數(shù)中是否存正則表達(dá)式模式,如果存在則返回true,否則返回false
reg.test('123.45'); //true
reg.test('0.2'); //true
reg.test('a.34'); //false
reg.test('34.5678'); //false
RegExp.prototype.exec(str)
方法用于正則表達(dá)式模式在字符串中運(yùn)行查找,如果exec()找到了匹配的文本,則返回一個(gè)結(jié)果數(shù)組,否則返回 null
除了數(shù)組元素和length屬性之外,exec()方法返回對象還包括兩個(gè)屬性。
index 屬性聲明的是匹配文本的第一個(gè)字符的位置
input 屬性則存放的是被檢索的字符串string
var str = '123 456 789
var reg = /\d{3}/g
while(result = reg.exec(str)){
console.log(result[0])
}
/*
123
456
789
*/
String.prototype.search(reg)
search() 方法用于檢索字符串中指定的子字符串,或檢索與正則表達(dá)式相匹配的子字符串
search() 方法不執(zhí)行全局匹配,它將忽略標(biāo)志g,它同時(shí)忽略正則表達(dá)式對象的lastIndex屬性,并且總是從字符串的開始進(jìn)行檢索,這意味著它總是返回字符串的第一個(gè)匹配的位置
'a1b2c3'.search(/\d/g); //1
'a1b2c3'.search(/\d/); //1
String.prototype.match(reg)
match()方法將檢索字符串,以找到一個(gè)或多個(gè)與regexp匹配的文本。但regexp是否具有標(biāo)志 g對結(jié)果影響很大。
var r = 'aaa123456'.match(/\d/)
console.log(r)? ? //["1", index: 3, input: "aaa123456"]
var r = 'aaa123456'.match(/\d/g);
console.log(r)? ? //["1", "2", "3", "4", "5", "6"]
String.prototype.replace(reg, replaceStr)
關(guān)于string對象的replace方法,我們最常用的是傳入兩個(gè)字符串的做法,但這種做法有個(gè)缺陷,只能replace一次
'abcabcabc'.replace('bc','X'); //aXabcabc
replace方法的第一個(gè)參數(shù)還可以傳入RegExp對象,傳入正則表達(dá)式可以使replace方法更加強(qiáng)大靈活
'abcabcabc'.replace(/bc/g,'X'); //aXaXaX
'abcaBcabC'.replace(/bc/gi,'X'); //aXaXaX
String.prototype.replace(reg, function)
可以通過修改replace方法的第二個(gè)參數(shù),使replace更加強(qiáng)大,在前面的介紹中,只能把所有匹配替換為固定內(nèi)容,但如果我希望把一個(gè)字符串中所有數(shù)字,都用小括號包起來該怎么弄
'2398rufdjg9w45hgiuerhg83ghvif'.replace(/\d+/g,function(r){
return '('+r+')';
}); //"(2398)rufdjg(9)w(45)hgiuerhg(83)ghvif"
String.prototype.split(reg)
我們經(jīng)常使用split方法把字符串分割為字符數(shù)組
'a,b,c,d'.split(','); //["a", "b", "c", "d"]
和replace方法類似,在一些復(fù)雜的分割情況下我們可以使用正則表達(dá)式解決
'a1b2c3d'.split(/\d/); //["a", "b", "c", "d"]
var str = 'sad? afqf sadvsdvs? ? sdvsdf ss? qwe'
str.split(/\s+/)? ? //["sad", "afqf", "sadvsdvs", "sdvsdf", "ss", "qwe"]
str.split(/\s*/)? ? // ["s", "a", "d", "a", "f", "q", "f", "s", "a", "d", "v", "s", "d", "v", "s", "s", "d", "v", "s", "d", "f", "s", "s", "q", "w", "e"]
判斷用戶提交信息是否符合規(guī)則
空白字符:回車。換行,制表符