正則表達式常見坑與分析法
前言
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions
這個開發(fā)者文檔就是好哼丈,講得比w3school還清楚
稍稍看看文檔唱遭,對照著就開始用吧。為啥要用正則呢掀鹅?不用多說了吧局蚀,一行正則匹配喷兼,頂上十來行字符串[拼接晒屎、分割棵介、截取]的操作
常見問題
-
字符串中的斜桿
\
有轉義
的特殊意義钉鸯,在寫正則規(guī)則的時候請注意\
代表的意思字符串中兩個
\
代表一個 -
/^ $/
中間的內容是只能包含的意思,而不是很多教程中提到的 以xxx開頭 邮辽,以xxx結尾唠雕,多了一層并且
的意思,所以規(guī)則是只能
/^a$/
匹配以a開頭吨述,以a結尾的字符 所以 只能是a/^ab$/
匹配以a開頭岩睁,以b結尾的字符 所以只能是 ab -
x|y
迷惑的|
匹配運算,優(yōu)先級很混亂記得搭配上()
來使用揣云,()
在正則中表示一個分組匹配意為先結合
解決優(yōu)先級問題let reg = /^18|29$/; console.log(reg.test("1829")) //=> true console.log(reg.test("189")) //=>true console.log(reg.test("129")) //=>true console.log(reg.test("89")) //=>false /* let reg = /^(18|29)$/; 這樣才符合我們想要的情況 */
reg.test(str)
str.match(reg)
-
[]
中出現(xiàn)的規(guī)則一般都是本身的含義let reg = /^[@+]+$/; // 只能是以@+中的任何一個開頭捕儒,且它出現(xiàn)一次或者多次的匹配,[]里面的`+`就是本身意義 console.log(reg.test("@@")) // => true console.log(reg.test("@@"))
:
\d
組合詞的本身含義就是 0 ~ 9let reg = /^[\d]$/ // => 這個 `\d` 還是原始的 `\d`的意思 0 ~ 9 之間的數(shù)字 console.log(reg.test("d")) //false console.log(reg.test("\\")) //false console.log(reg.test("9")) //true
-
[]
中不存在多位數(shù)let reg = /^[18]$/ console.log(reg.test("8")) //true console.log(reg.test("9")) //true console.log(reg.test("18")) //false
此處翻譯為: 只能是 1 或者 8
let reg = /^[10-29]$/
此處翻譯為:只能是 1 或者 0到2 或者9
let reg = /^[18-29]$/
而這里會提示 是錯誤的正則式灵再,Range out of order in character class 字符內的范圍無序
: 就算在
/^[10-29]$/
中加入()
,\
也不行
- 在寫正則表達式的時候一定要注意 順序是
從左往右就近匹配
的肋层,善用小整體()
- 遇到
|
使用()
確定好正則的優(yōu)先級(()
的作用一:細節(jié)用法看分析法第一條) - 把大正則中的每個小正則 配合
exec
方法提取出來(()
的作用二:細節(jié)用法看分析法第五條)
分析法
1、是否為有效數(shù)
- 有如下數(shù)字需要正則匹配():驗證是否屬于一個合法數(shù)字
0
1
12
12.5
12.0
-12
+12
09
提取條件出來:
/*
1. 可能出現(xiàn) + - 號翎迁,也可能沒有栋猖,且有且只有一個
2. 0 - 9 都可以,但是多位數(shù)首位不能是 0
3. 小數(shù)部分可能有汪榔,可能沒有蒲拉,有的話有且只有一個點,且點后必須有數(shù)字
*/
轉化為正則表達式
let reg = /^[+-]?(\d|([1-9]\d+))(\.\d+)?$/
/*
條件1:
[+-]? +或者-出現(xiàn) 0 或者 1 次
(+|-)? 與上面相等
條件2:
(\d|([1-9]\d+))
\d為出現(xiàn)一位痴腌,
或者多位時雌团,首位不能為零,則再用一個 () 表示一個小分組士聪,且每次遇到 | 的時候使用 ()包起來
([1-9]\d+) 這里表示小分組是 或的另外一邊的一個整體锦援, 1 - 9 出現(xiàn)一次 或者多次
+ 為匹配前面的表達式出現(xiàn)一次或者多次
*/
2、密碼的有效性
需求:密碼是 6 - 16位剥悟,可以是數(shù)字灵寺、字母曼库、下劃線
/**/
let reg = /^(\w){6,16}$/
3、真實姓名驗證
需求:
驗證漢字:/^[\u4E00-\u9FA5]$/
有可能是翻譯過來的漢字名:肯多·洛夫斯基略板,也可能是新疆人名字尼格買提·阿布都(·漢字)
名字長度2 ~ 10位
測試用例可以使用:
- 肯多·洛夫斯基
- 尼格買提·阿布都
- 弗拉基米爾·弗拉基米羅維奇·普京
- 萊昂納多·迪·皮耶羅·達·芬奇
let reg = /^[\u4E00-\u9FA5]{2,10}(·[\u4E00-\u9FA5]{2,10})*$/
4毁枯、郵箱格式驗證
- 以數(shù)字字母下劃線開頭(下劃線有些郵箱也可以出現(xiàn)多次)
- @前面可以是數(shù)字、字母叮称、下劃線种玛、一、.這些符號
- 不能把-和.連續(xù)出現(xiàn)瓤檐,出現(xiàn)一次后面必須跟數(shù)字字母下劃線
- @后面的緊跟數(shù)字赂韵、字母 ,一到多位
- 企業(yè)郵箱.com.cn多域名情況
let reg = /^\w+((-\w+)|(\.\w+))*@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/;
5挠蛉、身份證號碼驗證
中國第二代居民身份證規(guī)則為:
- 目前為止只有18位
- 最后一位可能是大寫的X (代表是10)
- 身份證前6位代表居民所在省右锨、市、縣
- 中間八位是出生年月日
- 最后四位:
- 最后一位 X 或者 數(shù)字
- 倒數(shù)第二位 偶數(shù)為女 碌秸,奇數(shù)為男
- 其余兩位是經過算法 結合前6绍移、中8,后2位算出來的(非隨機)
/*如果只考慮位數(shù)與字符讥电,不考慮字符意義*/
let reg = /^(\d+){17}(\d|X)$/
let reg = /^(\d+X{0,1}){18}$/ /*這樣寫不行蹂窖,必須拆開前17位 + 后一位才行*/
/*附帶意義的匹配*/
let reg = /^(\d{6})(\d{4})(\d{2})(\d{2})(\d{2})(\d)(\d|X)$/
reg.exec("430181199003073470")
使用
exec
來捕獲()
匹配出來的每一個小分組,結果為:
["430181199003073470", "430181", "1990", "03", "07", "34", "7", "0", index: 0, input: "430181199003073470", groups: undefined]
6恩敌、獲取cookie值
cookie 的規(guī)則:
字符串開頭有可能有空格瞬测,可能沒有(第一條就沒有)
接著后面是 key= 的固定樣式
字符串結束有可能有分號,可能沒有(最后一條沒有分號)
利用構造函數(shù)方式來獲取指定的 cookie key 名的值
function (key) {
let reg = RegExp("(^| )"+key+"=([^;]*)(;|$)");
}
/*
* exec 有幾個括號就至少有幾個分組
* 匹配一個開頭,空格可有可無 (可能匹配的是第一條纠炮,所以空格可有可無)
* 接著后面的 字符是 key=
* 匹配任何沒有包含在方括號中的字符 (只要不是分號就可以)
* 星號 = {0,} 出現(xiàn)零次或者多次月趟,意味著 cookie有時候會是 null值
* 匹配結束 分號可有可無(可能匹配的是最后一條,所以分號可有可無)(只能包含 ^ $ 中間的東西)
* */
[" name=zhangsan", " ", "zhangsan", "", index: 22, input: "age=21; handsome=true; name=zhangsan", groups: undefined]
如果 傳入?yún)?shù) name,匹配之后:
/*
* 可以看到 name 前面有空格恢口,
* 第一項為 匹配出來的總結果
* 第二項的 " " 為 小分組 (^| ) 所捕獲
* 第三項的 "zhangsan" 為 小分組([^;]*)所捕獲 這正是我們想要的
* 第四項的 "" 為 小分組(;|$) 所捕獲
* */
// 返回的數(shù)組中 input 是原生字符串 是 document.cookie
正則表達式的兩種創(chuàng)建方式
1孝宗、字面量方式
let reg = /@+name+/
/ /
中間包含的任意字符都會被識別成為 正則表達式的元字符
如果這個時候要將 傳過來的變量
name
來進行獨立的個體匹配,那是不行的耕肩,這個時候就應該用構造函數(shù)方式
來創(chuàng)建字符串拼接
的表達式注意:使用正則表達式字面量為正則表達式提供了腳本加載后的編譯因妇。當正則表達式保持不變時,使用此方法可獲得更好的性能猿诸。
2婚被、構造函數(shù)方式
new RegExp(pattern,flags)
pattern
:正則表達式
flags
:匹配模式
let reg = new RegExp("@"+name+"+")
且在使用模式的時候需要傳入第二個參數(shù)
flags
字面量的方式可以緊隨最后一個
/
其后注意:使用構造函數(shù)為正則表達式提供了運行時的編譯。使用構造函數(shù)的方式梳虽,當你知道正則表達式的模式將會改變址芯,或者你不知道模式,并且從其他來源獲取它,如用戶輸入谷炸。
var regex1 = /\w+/;
var regex2 = new RegExp('\\w+'); //在字符串中 單條斜桿加上斜桿后字符代表轉義字符
console.log(regex1);
// expected output: /\w+/
console.log(regex2);
// expected output: /\w+/
console.log(regex1 === regex2); //兩個雖然輸出一樣删顶,但是不相等
// expected output: false