一、正規表示式
1.1正則概述和體驗
正規表示式是被用來匹配字串中的字元組合的模式,常用來做表單驗證。在JavaScript中,正規表示式也是物件,是一種引用型別。
案例:正確輸入一個電話號碼,010-12345678,使用者輸入正確返回“對”,錯誤返回“錯”
var tel = prompt("請輸入電話號碼"); var reg = /^\d{3}-\d{8}$/; if(reg.test(tel)){ alert("對"); }else{ alert("錯"); }
字串的方法:
split() 根據匹配把字串分割為字串陣列。
match() 使用正規表示式與字串相比較,返回一個包含匹配結果的陣列。
search() 對正規表示式或指定字串進行搜尋,返回第一個出現的匹配項的下標。
replace() 替換與正規表示式匹配的字串。
正規表示式方法:
exec() 檢索字串中指定的值。返回找到的值,並確定其位置。
test() 檢索字串中指定的值。返回 true 或 false。
注意:任何資料自己的方法,都要自己對應資料打點呼叫
字串:打點呼叫字串方法
正則:打點呼叫正則方法
1.2正規表示式
使用一個正規表示式字面量是最簡單的方式,兩個“//”是正規表示式的定界符。
正規表示式:Regular Expression,通常簡寫為:RegExp
語法:
/正則符號/ |
/abc/ 表示匹配的是一個abc三個字元,而且三個字元必須同時連在一起,順序不能顛倒。 |
var reg = /abc/; //正規表示式字面量,儘量賦值給一個變數 |
console.log(typeof reg); //object |
正規表示式是一種物件資料型別,引用型別的其中一種,變數儲存的是正則物件的地方。
1.3字串方法
split()方法用於把字串分割成陣列(字串→陣列),從什麼地方拆分,就是引數
var str = "aa bbb c dddd eeee ffff"; console.log(str.split(" ")); //如果用字串方法進行分割,一個空格分割 console.log(str.split(/\s+/)); //正規表示式可匹配一個或多個空白字元 |
//用a當分割符 var str = "bbbbaaacccaaaddddaeeeeaaaafff"; console.log(str.split(/a+/)); //匹配a,+號表示並且出現一次或多次 |
match()使用正規表示式與字串相比較,返回包含匹配結果的陣列。
可在字串內檢索指定的值,或找到一個或多個正規表示式的匹配。預設:返回找到的第一個字元組成陣列。
var str = "bbbbaaacccaaaddddaeeeeaaaafffbbb"; console.log(str.match(/a/)); //返回匹配第一次出現結果的字元 console.log(str.match(/a+/)); //返回匹配結果的多個字元 console.log(str.match(/a+/).index); //返回匹配結果的下標 |
var str = "aaa o o bbbb o o aaaa"; console.log(str.match(/o\s+o/g)); //g 全域性匹配 |
使用正規表示式作為分隔符,可以進行模糊匹配
\s 表示匹配空白字元 + 表示前面的字元出現一次或多次 g 全域性定界符,全域性匹配 |
search()對正規表示式或指定字串進行檢索,返回第一個出現的匹配項下標位置。(無視全域性定界符)
var str = "abcdefgcd"; console.log(str.search("cd")); //2,字串匹配 console.log(str.search("cdf")); //-1,沒有匹配返回-1 console.log(str.search(/cd/g)); //2,正則匹配,無視全域性定界符g var str = "aaa o t o o bbbb o o aaaa"; console.log(str.search(/o\s+o/)); //10,字串匹配 console.log(str.search(/o\so/g)); //-1,不能完全匹配
值為-1,表示字串內沒有匹配的項,或者不能完全匹配。
replace()替換與字串匹配或正規表示式匹配的子串。
兩個引數:
引數1:匹配原字串的字元(可以是字串、正則)
引數2:替換的新字元。產生新字串,不影響原字串。
//需求:將www.webqianduan.cn 替換乘www.iqianduan.cn var str = "www.webqianduan.cn"; console.log(str.replace("webqianduan","iqianduan")); //字串匹配替換 console.log(str.replace(/webqianduan/,"iqianduan")); //正則匹配替換 console.log(str); //不影響原字串
replace第二引數還可以是函式,$1表示正則匹配到的第一個結果,$2是第二個結果,以此類推,如果同時更改兩個匹配結果可以返回一個陣列。
var str = "www.webqianduan.cn"; var arr = str.replace(/\.(\w+)\./,function(match,$1){ console.log(match,$1); return ".iqianduan." }); console.log(arr);
//如果沒有()匹配的話函式的引數分別為:當前匹配的字元(match),當前匹配字元的位置(pos),原始字串(origin) var text = 'cat,bat,sat,fat'; var result = text.replace(/cat,bat/, function (match, pos, originalText) { console.log(match, pos, originalText); return 'ond'//將匹配到的更換成ond }); console.log(result);//ond,sat,fat
練習:過濾字串中的空格
var str1 = "aa b c d e f"; console.log(str1.replace(/\s+/g,"")); |
1.4正規表示式方法
正規表示式方法:
exec() 檢索字串中指定的值。返回找到的值,並確定其位置。
test() 檢索字串中指定的值。返回 true 或 false。
exec()在字串中去匹配正規表示式,如果有輸出第一個到陣列中。(無視全域性定界符g)
可以通過index屬性獲取原字串下標。
var str = "fuahndabcfnkandabc"; console.log(/abc/.exec(str)); console.log(/abc/.exec(str).index); //下標為6 |
var str = "oooooo 0 0 ooooo"; var reg = /o\s+0\s+0\s+o/; console.log(reg.exec(str)); console.log(reg.exec(str).index); //下標為5
test() 檢索字串中指定的值(匹配正規表示式)。有返回 true,沒有返回false。
var str = "aaddccccdddabcd"; var reg = /abc/; //精確匹配 console.log(reg.test(str)); //true console.log(str.search(reg)); //11 //練習檢測"a bc"和"abc"是否包含空格 var str1 = "a bc"; var str2 = "abc"; var reg = /\s+/; console.log(reg.test(str1));//true console.log(reg.test(str2));//false
二、正則的術語和操作符
正規表示式:
由一些普通字元和一些特殊字元(又叫元字元--metacharacters)組成。普通字元包括大小寫的字母和數字,而元字元則具有特殊的含義。
特殊字元,javascript中常用特殊字元有:
( ) [ ] { } \ ^ $ | ? * + .
若想匹配這類字元必須用轉義符號“\” 如:“\.”“\^” , “\\”
2.1精確匹配
精確匹配指的是要去匹配某一個固定值或常量,匹配abc,正規表示式裡必須用精確的術語進行匹配。
正規表示式:/abc/ ,表示要匹配三個字元,分別是abc必須是順序在一起。
精確匹配沒有特殊符號:
2.2預定義特殊符號
預定義特殊字元:
\t /\t/ 製表符 eg: console.log(/\t/.test(' '))
\n /\n/ 回車符 eg: console.log(/\n/.test(`aaa
bbb`));
\f /\f/ 換頁符
\t製表符:
\n回車符:
回車符:不能直接敲回車換行,使用``這對引號包裹可以直接換行。
2.3字符集
用正規表示式中的一類字元去匹配字串中的一個字元。字符集用[]包括。
比如[abc],表示可以匹配a,也可以匹配b,也可以匹配c,只要存在其中一個都是對的。
簡單類:正則的多個字元對應一個字元,可以用[]把它們括起來,讓[]這個整體對應一個字元。將所有可能性都列在[]內,不要出現其他字元,直接連寫。
var str = "fiafiortfasoztfakoct"; console.log(str.match(/o[rzc]t/g)); |
範圍類:有時候匹配的東西過多,而且型別又相同,全部輸入太麻煩,我們可以在中間加個短橫線。
[0-9] 查詢任何從 0 至 9 的數字。
[a-z] 查詢任何從小寫 a 到小寫 z 的字元。
[A-Z] 查詢任何從大寫 A 到大寫 Z 的字元。
[A-z] 查詢任何從大寫 A 到小寫 z 的字元。
var str = "oo1234abcdfABCDFAAE"; console.log(str.match(/o[0-9]/g)); //["o1"] console.log(str.match(/o[a-z]/g)); //["o1"] console.log(str.match(/a[a-z]c/g)); //["abc"] console.log(str.match(/B[A-Z]D/g)); //["BCD"]
組合類:允許用中括號匹配不同型別的單個字元。
[0-9a-zA-Z]:表示匹配的可以是數字、小寫字母、大寫字母。
// o開頭c結尾,中間任意一個字元 var str = "abc123a8c123aBca3c"; console.log(str.match(/a[0-9a-z]c/g)); console.log(str.match(/a[0-9a-zA-Z]c/g)); console.log(str.match(/a[5-9A-F]c/g)); console.log(str.match(/a[5-9abc]c/g));
負向類:[]前面加個元字元“^”進行取反,表示匹配不能為括號裡面的字元 [^a]
var str = "abcortaaaaoctbbbo4toPt"; console.log(str.match(/o[^a-z]t/g)); console.log(str.match(/o[^A-Z]t/g)); console.log(str.match(/o[^0-9]t/g)); console.log(str.match(/o[^0-9abc]t/g));
2.4修飾符
g :全域性修飾符,修飾符用於執行全域性匹配(查詢所有匹配),一直到將所有可能性都匹配成功。
global:全域性、全球。使用時的位置:在正則的字面量//後面。match、replace方法都可以使用g
var str = "01222a333b56c7890de"; console.log(str.match(/[0-9]+/)); console.log(str.match(/[0-9]+/g)); console.log(str.match(/a[0-9]+/g));
i :修飾符,用於執行大小寫不敏感匹配
var str = "aabbbcccAAcAaa"; console.log(str.match(/aa/g)); console.log(str.match(/aa/gi)); //大小寫不敏感 |
注意:修飾符位置,都是//後面,修飾符可以同時使用,連寫就可以了。
2.5邊界
^ :開頭,不能寫在[]中,如果寫在[^]是取反的意思。
匹配的是字串必須以什麼開頭。^後面的正則術語匹配的字串必須是開頭。
console.log(/^hello/.test("hello javascript")); //true console.log(/^hello/.test("helo javascript")); //false console.log(/^hello/.test("hhello javascript")); //false console.log(/^hh/.test("hhello javascript")); //true
$ :結尾,匹配的是必須以$前面的字元為結尾(必須完全匹配),$寫在正則裡面//的最後。
console.log(/javascript$/.test("hello javascript")); //true console.log(/javascript$/.test("hello javascript$")); //false console.log(/javascript$/.test("hello javascript@")); //false console.log(/javascript@$/.test("hello javascript@")); //true
^和$可以同時使用,必須以他們中間的內容當做開頭和結尾,字串只能有中間的內容。
console.log(/^[0-9]+$/.test(8888888888888)); //true console.log(/^[0-9]+$/.test("88888abc888")); //false console.log(/^[0-9abc]+$/.test("88888abc888")); //true console.log(/^[a-zA-Z][0-9a-zA-Z]+$/.test("88888abc888")); //false console.log(/^[a-zA-Z][0-9a-zA-Z]+$/.test("abc888abc888")); //true console.log(/^[a-zA-Z][0-9a-zA-Z]*$/.test("a1234aaa")); //true console.log(/^[a-zA-Z][0-9a-zA-Z]+$/.test("a")); //true console.log(/^[a-zA-Z]bbb[0-9a-zA-Z]+$/.test("abbba")); //true
\b 單詞邊界,用於查詢位於單詞的開頭或結尾的匹配
限定匹配的字元必須位於單詞的邊界,配合其他的字元匹配時,\ba表示a字元必須匹配,而且a必須位於單詞的開頭,c\b表示c字元匹配必須位於單詞的結尾。
console.log(/\ba/.test("apple")); //true console.log(/\ba/.test("iapple")); //false console.log(/\ba/.test("i apple")); //true console.log(/ple\b/.test("i apple")); //true console.log(/e\b/.test("i apple")); //true var str = 'i love JavaScript very much@pei'; console.log(str.match(/\b[a-z]/gi)); console.log(str.match(/\b[a-z]+/gi));
\w,表示查詢單詞字元,包含數字、大小寫字母、下劃線
console.log("we are family no".match(/\w+/g)); console.log("we are family no".match(/\b\w+\b/g)); console.log("we are Family no".match(/\b[a-z]+\b/g)); console.log("We Are Family No".match(/\b[a-z]+\b/g)); console.log("We Are Family No".match(/[a-z]+\b/g));
\B 匹配非單詞邊界,用於查詢不在單詞的開頭或結尾。
\B寫在前面,表示後面那個字元匹配時必須不是一個單詞的開始。
\B寫在後面,表示前面那個字元匹配時必須不是一個單詞的結尾。
var str = 'i love JavaScript very much@pei'; console.log(str.match(/\b[a-z]+\b/gi)); console.log(str.match(/\B[a-z]+\B/gi));
對比記憶:單詞邊界\b必須包含單詞邊界,非單詞邊界\B不能有單詞邊界。
2.6預定義類(元字元)
預定義類其實都是對一些字符集的簡寫。
.[^\n\r] 除了換行和回車之外的任意字元
console.log(/.+/.test("!@#$%#$%^gjsdhbf11222")); //true console.log(/^.+$/.test(`!@#$%#$%^gjsdh bf11222`)); //false
\d[0-9]只匹配數字字元,一個\d只能匹配一個數字
console.log(/^\d$/.test(0123456789888)); //false console.log(/^\d+$/.test(0123456789888)); //true console.log(/^\d+$/.test('0123456789a888')); //false
\D[^0-9]匹配非數字字元,只要不是數字都可以
console.log(/^\D+$/.test(0123456789888)); //false console.log(/^\D+$/.test("0123457aa89888")); //false console.log(/^\D+$/.test('abc@#$%^&你好abc')); //true
\s[\t\n\x0B\f\r]匹配空白字元、空格、縮排、換行、換頁
console.log(/\s+/.test(`你好 啊!!`)); //true,匹配到換行 console.log(/\s+/.test('你好 ')); //true console.log(/^\s+/.test('你好 '));//false console.log(/^\s+/.test(' 你好 '));//true
\S[^\t\n\x0B\f\r]匹配非空白字元(除了空白符都可以)
console.log(/^\S+$/.test(" 你好 ")); //false console.log(/^\S+$/.test(" 你好 ")); //false console.log(/^\S+$/.test("!@#$%abc13")); //true
\w[a-zA-Z_0-9]單詞字元(所有的大小寫字母/數字/下劃線)
console.log(/^\w+$/.test('abc12345ABC_dd')); //true console.log(/^\w+$/.test('abc12345ABC_dd#@')); //false console.log(/^\w+$/.test('abc12345ABC_dd文字')); //false console.log(/^\w+$/.test('abc12345ABC_dd ')); //false
\W[^a-zA-Z_0-9]匹配非單詞字元(非所有的大小寫字母/數字/下劃線)
console.log(/^\W+$/.test('abc12345ABC_dd')); //false console.log(/^\W+$/.test('你好,#¥%……&&')); //true console.log(/^\W+$/.test(' ')); //true
2.7量詞
有一些字元進行匹配時,連續多個可能是相同的字元,提供量詞去解決出現重複次數的書寫方式。
規定數量:作用範圍是量詞前面的一個字元。
{n} 硬性量詞,內部寫對應重複次數。
console.log(/ab{3}c/.test('abbbc')); //true console.log(/ab{3}c/.test('abbc')); //false console.log(/ab{3}c/.test('abbbbc')); //false
{n,m} 軟性量詞,至少出現n次但不超過m次(中間不能有空格)。
大於等於n次,小於等於m次。
console.log(/ab{3,5}c/.test('abbc')); //false console.log(/ab{3,5}c/.test('abbbc')); //true console.log(/ab{3,5}c/.test('abbbbbc')); //true console.log(/ab{3,5}c/.test('abbbbbbc')); //false
{n,} 軟性量詞,至少出現n次(+的升級版)。
可以出現n次或更多次,上不封頂,但不能小於n次
console.log(/ab{3,}c/.test('abbc')); //false console.log(/ab{3,}c/.test('abbbc')); //true console.log(/ab{3,}c/.test('abbbbbbbc'));//true
? 軟性量詞,出現零次或一次,等價於{0,1}
console.log(/ab?c/.test('ac')); //true console.log(/ab?c/.test('abc')); //true console.log(/ab?c/.test('abbbbc')); //false
* 軟性量詞,出現零次或多次 等於{0,}
console.log(/ab*c/.test('ac')); //true console.log(/ab*c/.test('abc')); //true console.log(/ab*c/.test('abbbbc')); //true
+ 軟性量詞,出現一次或多次(至少一次),等價於{1,}
console.log(/ab+c/.test('ac')); //false console.log(/ab+c/.test('abc')); //true console.log(/ab+c/.test('abbbbc')); //true
量詞除了修飾前面的單個字元,還可以搭配預定義類使用。
2.8分組
雖然量詞的出現,能幫我們處理一排緊密相連的同類字元,但這還不夠,我們需要重複的字元不是一個或多個,就要用小括號對多個字元進行分組。
console.log(/(bye){2}/.test('bye')); //false console.log(/(bye){2}/.test('byebye')); //true console.log(/bye{2}/.test('byeee')); //true
2.9或操作符
可以使用豎線“|”字元表示或者的關係。
“|”前面或後面,如果沒有限制,會將“或”前後分為兩個整體,只要匹配成功一個就可以。
a|bcd:表示匹配的字串,要麼包括一個單獨的a,要麼包括一個整體bcd
console.log(/^12|abc$/.test('1abc')); //true console.log(/^12|abc$/.test('abc')); //true console.log(/^12|abc$/.test('12')); //true console.log(/^12|abc$/.test('12abc'));//true
可以利用圓括號來分組,將“|”操作符包裹起來,就跟後面沒關係
(a|b)cd;表示從a、b選其一,後面是cd
console.log(/^a(d|b)c$/.test('bc')); //false console.log(/^a(d|b)c$/.test('abc')); //true console.log(/^a(d|b)c$/.test('adc')); //true console.log(/^a(d|b)c$/.test('ad')); //false
驗證一個月31天內都為真:
console.log(/^((0?[1-9])|((1|2)[0-9])|30|31)$/.test(28)); |
2.10反向引用
反向引用標識是對正規表示式中的匹配組捕獲的子字串進行編號,通過“\編號(在表示式中)”,“$編號(在表示式外)”進行引用。從1開始計數。
正規表示式中一個分組的符號,會在字串中找到匹配的結果,這個匹配這個可以用個一些特殊的書寫反向引用。
在正規表示式中反向引用“\編碼”,從1開始
在正規表示式外反向引用“$編碼”,從1開始
console.log(/\w{3}/.test('bye')); //true console.log(/(\w{3})\1/.test('byebye')); //true console.log(/(\w{3})\1/.test('bye')); //false console.log(/(\w{3})\1/.test('byehhh')); //false console.log(/(\w{3})\1\1/.test('byebyebye')); //true console.log("123*456".replace(/(\d{3})\*(\d{3})/,'$2==$1'));
除了直接反向引用之外,還可以對引用的字元做一些複雜的操作
replace()第二引數還可以是函式,$1表示正則匹配到的第一個結果,$2是第二個結果,以此類推
函式的引數分別為:當前匹配的字元(match),當前匹配字元的位置(pos),原始字串(origin)
替換函式必須有返回值,它才會去替換新內容。
var reg = "123*456".replace(/(\d{3})\*(\d{3})/,function(match,$1,$2){ return $2 + '*****' + $1; //return parseInt($1) + parseInt($2); }); console.log(reg);
2.11中文匹配
匹配中文固定語法:[\u4e00-\u9fa5]
console.log(/^[\u4e00-\u9fa5]+$/.test("愛前端")); //true console.log(/^[\u4e00-\u9fa5]+$/.test("愛前端iqianduan")); //flase console.log(/^[\u4e00-\u9fa5]+$/.test("愛前端123")); //flase console.log(/^[\u4e00-\u9fa5]+$/.test("愛前端繁體")); //true var str = prompt("請輸入使用者名稱,必須是4-6位漢字!"); var reg = /^[\u4e00-\u9fa5]{4,6}$/; if(reg.test(str)){ alert("對"); }else{ alert("錯誤"); }