正規表示式並不難,只是很多人用得少所以記不住,但並不能否認它的強大之處!
正規表示式的作用
- 校驗字串文字是否符合規則
- 提取符合規則的文字內容
- 替換文字內容
正則的字元含義
字元 | 描述 |
---|---|
. |
匹配除換行符外的任意字元,一個點只能匹配一個 |
\w |
匹配字母數字下劃線或者漢字 |
\W |
匹配任意不是字母,數字,下劃線,漢字的字元 |
\s |
匹配空白字元,它和[ \t\n\r]等價(分別是空格製表符換行符回車符) |
\S |
匹配任意不是空白符的字元 |
\d |
匹配數字(只能表示一位數字,可以替換為[0-9]) |
\D |
匹配任意非數字的字元 |
\b |
匹配單詞的開始或結束 |
\B |
匹配不是單詞開頭或結束的位置 |
^ |
匹配字串的開始,在列舉的上面表示非,如[^\d] |
a-Z |
匹配a-Z之間的任意字元 |
$ |
匹配字串的結束 |
* |
重複零次或多次 |
+ |
重複一次或更多次 |
? |
重複零次或一次 |
{n} |
重複n次 |
{n,} |
重複n次或更多次 |
{n,m} |
重複n到m次 |
() |
表示分組,就是括號裡面的作為一個整體 |
[] |
表示字串的列舉 |
相關方法
test()
- 用於檢測字串是否符合正則規定
let str = 'javascript'
let reg = /java/
// 檢測字串是否包含'java'
console.log(reg.test(str)); //true
match()
- match()可以檢索一個字串或者一個正則的匹配,並將匹配到的結果通過陣列返回,如果未加全域性匹配,則只能通過陣列返回匹配到的第一項結果,並會附加資訊
var str="1 plus 2 equal 3"
console.log(str.match('equal')); //[ 'equal', index: 9, input: '1 plus 2 equal 3', groups: undefined ]
console.log(str.match(/\d+/)); //[ '1', index: 0, input: '1 plus 2 equal 3', groups: undefined ]
console.log(str.match(/\d+/g)); //[ '1', '2', '3' ]
replace()
- replace() 方法用於在字串中用一些字元替換另一些字元,或替換一個與正規表示式匹配的子串
stringObject.replace(regexp/substr,replacement)
- 引數一為要替換的子字串或要替換的模式的正則物件
- 規定了替換文字或生成替換文字的函式
var str="Visit Microsoft!"
console.log(str.replace('Microsoft', "W3School")); //Visit W3School!
console.log(str.replace(/Microsoft/, "W3School")); //Visit W3School!
exec()
- exec() 方法用於檢索字串中的正規表示式的匹配
- 通過exec()匹配到的每一項有效結果都會附加資訊
- 在都是非全域性匹配的模式下,exec()返回的結果與match()相同;如果是全域性匹配,exec()每被呼叫一次都會返回一項結果陣列,直到無法匹配到內容時停下,返回null
let str="1 plus 2 equal 3"
let reg = /\d/g
console.log(reg.exec(str)); //[ '1', index: 0, input: '1 plus 2 equal 3', groups: undefined ]
console.log(reg.exec(str)); //[ '2', index: 7, input: '1 plus 2 equal 3', groups: undefined ]
console.log(reg.exec(str)); //[ '3', index: 15, input: '1 plus 2 equal 3', groups: undefined ]
console.log(reg.exec(str)); //null
應用例項
檢測手機號
-
11位數
-
第1位為1,第2位在(3,4,5,6,7,8,9)中選1位,3~11位為數字即可
function isPhoneNumber(tel) {
var reg =/^1[3-9]\d{9}$/;
return reg.test(tel);
}
isPhoneNumber('13997584510')
檢測郵箱
- 以@為分隔符,在@之前以字母、數字開頭,之後還可以跟隨減號(-)或小數點(.),但不能同時跟隨
- @之後必須緊跟字母或數字
- 在此之後應緊跟至少一個特殊字元小數點(.)或減號(-),減號(-)可有可無,但是小數點(.)必須存在,並且以小數點後結尾,兩種特殊字元也可以共存。不管是小數點(.)還是減號(-),後面都要求跟字母或數字
function isEmail(str){
var reg = /^[A-Za-z0-9]+[-\.]*@[A-Za-z0-9]+(-[A-Za-z0-9])*\.[A-Za-z0-9]+$/;
return reg.test(str);
}
isEmail('2270877057@qq.com')
郵箱由於格式種類眾多,因此想用一個正則能夠檢測出所有的郵箱使不現實的,這使得郵箱的檢測必定不會完美
檢測密碼強度
-
按照密碼強度標準,根據打分機制評定密碼強度
-
長度(25分)
- 5 分: 小於等於 4 個字元
- 10 分: 5 到 7 字元
- 25 分: 大於等於 8 個字元
-
字母組成(25分)
- 0 分: 沒有字母
- 10 分: 包含字母但全都是小(大)寫字母
- 25 分: 包含大小寫混合字母
-
數字組成(20分)
- 0 分: 沒有數字
- 10 分: 1或2個數字
- 20 分: 大於 2 個數字
-
其它特殊符號(@#$%^&*)(25分)
- 0 分: 沒有符號
- 10 分: 1 個符號
- 25 分: 大於 1 個符號
-
額外獎勵(5分)
- 2 分: 字母和數字
- 3 分: 字母、數字和符號
- 5 分: 大小寫字母、數字和符號
-
最後評分標準:
分數 等級 >=90 非常安全 >=80 安全 >=70 非常強 >=60 強 >=50 一般 >=25 弱 >=0 非常弱 -
由於檢測規則較為複雜,因此借用了方法判斷
// 獲取總分數
function getTotalScore(password) {
let totalScore = 0
const regLowLetter = /[a-z]+/g
const regUpLetter = /[A-Z]+/g
const regAllLetter = /([a-z]+[A-Z]+)|([A-Z]+[a-z]+)/g
const regSpecialChar = /[@#$%^&*]+/g
const specialCharNum = password.match(regSpecialChar) ? password.match(regSpecialChar)[0].length : 0
const regNumber = /\d*/g
const numberLen = password.length - password.replace(regNumber, '').length
const extral2 = /^(?=.*[a-zA-Z])(?=.*\d).*$/
const extral3 = /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[@#$%^&*]).*$/
const extral5 = /^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&*]).*$/
// 檢測字元長度
if (password.length >= 8) {
totalScore += 25
} else if (5 <= password.length) {
totalScore += 10
} else {
totalScore += 5
}
// 檢測字母
if (regAllLetter.test(password)) {
totalScore += 25
} else if (regLowLetter.test(password) || regUpLetter.test(password)) {
totalScore += 10
} else {
totalScore += 0
}
// 檢測數字
if (numberLen >= 3) {
totalScore += 20
} else if (0 < numberLen) {
totalScore += 10
} else {
totalScore += 0
}
// 檢測其他字元
if (specialCharNum == 1) {
totalScore += 10
} else if (specialCharNum > 1) {
totalScore += 25
} else {
totalScore += 0
}
// 額外獎勵
if (extral5.test(password)) {
totalScore += 5
} else if (extral3.test(password)) {
totalScore += 3
} else if (extral2.test(password)) {
totalScore += 2
} else {
totalScore += 0
}
return totalScore
}
// 獲取級別
function getRank(password) {
let totalScore = getTotalScore(password)
switch (true) {
case totalScore >= 90:
console.log('密碼非常安全');
break;
case totalScore >= 80:
console.log('密碼安全');
break;
case totalScore >= 70:
console.log('密碼非常強');
break;
case totalScore >= 60:
console.log('密碼強');
break;
case totalScore >= 50:
console.log('密碼一般');
break;
case totalScore >= 25:
console.log('密碼弱');
break;
case totalScore >= 0:
console.log('密碼非常弱');
break;
}
}
getRank('ahhi1233217890#0')
替換文字
- 以替換首尾空格為例,模擬
trim()
方法
function replaceText(text) {
var reg = /^\s*|\s*$/;
return text.replace(reg, '')
}
replaceText(' Jfsd4324--_ ');
提取文字
- 將windows後面跟著的版本號一起提取出來
let text = 'Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively.Windows 95 and Windows 98 are the successor.Then Windows 2000 and Windows Xp appeared.Windows Vista is the Latest version of the family.'
function extractTetx(text) {
let reg = /Windows ([\d.]|[a-zA-Z])+\b/g
return text.match(reg)
}
console.log(extractTetx(text));
檢測身份證
-
身份證的規則:
- 15位:
ai = xxxxxx yymmdd aa g
- 18位:
ai = xxxxxx yyyymmdd aa g p
-
x
是6位是地區編碼,地區編碼首位不能為0 -
ymd
分別表示年月日,表示出生日期,aa
是隨機碼,g是性別,p是校驗碼
- 15位:
-
校驗碼計算規則:
-
前17位號碼加權因子為
Wi = [ 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 ]
-
驗證位
tt = [ 1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2 ]
-
校驗碼
p = tt[i]
,其中 ,i是公式除11後取得的餘數,如2.31則 i=3,2.37 則 i =4
-
-
由於檢測規則較為複雜,因此借用了方法判斷
// 判斷是否是身份證的核心方法
function isIDCard(str) {
let getBirthday
// 獲取身份證最後一位數,用於核對校驗碼
let getLastNum = str.slice(-1, )
if (str.length == 15) {
getBirthday = str.slice(6, 12)
// 出生日期核對(15位身份證無校驗碼)
if (!(birthRule(getBirthday))) {
return false
}
} else {
getBirthday = str.slice(6, 14)
// 校驗碼與生出日期核對
if (!(birthRule(getBirthday) && countLastNum(str) == getLastNum)) {
return false
}
}
// 正則核對
let reg = /(^[1-9]\d{13}(\d{3}[Xx]|\d{4})$)|(^[1-9]\d{11}(\d{3}[Xx]|\d{4})$)/;
return reg.test(str);
}
// 判斷生日是否合法(string:birthday)
function birthRule(birthday) {
let year = birthday.slice(0, -4)
let month = birthday.slice(-4, -2)
let day = birthday.slice(-2, )
if (year.length === 2) {
year = '19' + year
}
if (year > new Date().getFullYear() || month > 12) {
return false
}
let days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
// 閏年
if ((year % 100 !== 0 && year % 4 === 0) || year % 400 === 0) {
days[1] = 29
}
if (day > days[month - 1]) {
return false
}
return true
}
// 計算校驗碼(即使用上述公式)
function countLastNum(idCard) {
let tt = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2]
let wi = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
let arr1 = []
let totalNum = 0
let arr2 = idCard.slice(0, 17).split('')
arr2.forEach((item, i) => {
arr1.push(parseInt(item) * wi[i])
});
totalNum = arr1.reduce((total, value) => total + value)
return tt[mod(totalNum, 11)] - 1
}
// 取餘函式
function mod(den, mol) {
return parseInt((den / mol).toFixed(1).toString().split('.')[1])
}
console.log(isIDCard('422301196912307153'));
檢測QQ號
- qq號的規則非常簡單:
- 5~11位數
- 首位不能為0
function isQQ(qq) {
var reg = /^[1-9]\d{4,10}$/;
return reg.test(qq);
}
console.log(isQQ('13997584510'));
檢測微訊號
- 必須以字母開頭,可以使用6-20位字母、數字、下劃線或減號(-)組合。
- 不能設定中文
function isWeiXin(weiXin) {
var reg = /^[a-zA-Z][a-zA-Z0-9_-]{5,19}$/;
return reg.test(weiXin);
}
console.log(isWeiXin('J13997584510'));