為什麼要使用正規表示式
正規表示式通過由普通字元和特殊字元組成的文字模板完成對字串的校驗,搜尋,替換。在javascript中類似這樣
/^1d{10}$/
上面的這個簡單的正則用來匹配手機號
至於說正規表示式到底有什麼意義,藉由《精通正規表示式》裡面的一句話來概括好了。
“如果羅列計算機軟體領域的偉大發明,我相信絕對不會超過二十項,在這個名單當中,當然應該包括分組交換網路,Web,Lisp,雜湊演算法,UNIX,編譯技術,關係模型,物件導向,XML這些大名鼎鼎的傢伙,而正規表示式也絕對不應該被漏掉。
對很多實際工作而言,正規表示式簡直是靈丹妙藥,能夠成百倍的提高開發效率和程式質量。”
正規表示式的生成
在javascript中生成正規表示式的方式有兩種
-
呼叫RegExp物件的建構函式
var reg = new RegExp(`^[a-z]+[0-9]$`, `gi`)
其中第一個引數是匹配模式,第二個引數是可選引數(g, i, m),分別用於指定全域性匹配、區分大小寫的匹配和多行匹配。這種方式會在正規表示式執行時編譯(runtime compilation)。如果你知道正規表示式模式將會改變,或者你事先不知道什麼模式,而是從另一個來源獲取,如使用者輸入,這些情況都可以使用建構函式。
-
使用正規表示式字面值,將匹配模式封閉在兩個斜槓中
var reg = /^[a-z]+[0-9]$/gi
當表示式被賦值時,字面量形式提供正規表示式的編譯(compilation),當正規表示式保持為常量時一般使用字面量方式。例如當你在迴圈中使用字面量構造一個正規表示式時,正規表示式不會在每一次迭代中都被重新編譯(recompiled)
正規表示式的組成
正規表示式的文字模板是有很多不同型別的字元組成的,包括:
元字元,轉義字元,限定符,字元組,或結構,括號分組
元字元
字元 | 含義 |
---|---|
. | 匹配除了換行符(n)以外的所有字元 |
w | 匹配字母,數字,下劃線 |
W | 匹配除了字母,數字,下劃線以外的其他字元 |
d | 匹配數字 |
D | 匹配除了數字以外的其他字元 |
s | 匹配任意的空白符(f, n, r, t, v) |
S | 匹配空白符以外的任意字元 |
b | 匹配單詞的開始或者結束 |
B | 匹配單詞的非開始或者結束 |
^ | 匹配行首 |
$ | 匹配行尾 |
轉義字元
* + ? | { [ ( ) ] }^ $ . # 和 空白 這些字元都是需要轉義的。例如我們要匹配{。
{
限定符
字元 | 含義 |
---|---|
* | 匹配零次至多次 |
+ | 匹配一次至多次 |
? | 匹配零次或一次 |
{2,} | 至少匹配兩次 |
{10} | 匹配10次 |
{{2, 8}} | 至少匹配兩次之多匹配八次 |
字元組[]
中括號字元組用來匹配括號內的字元之一
`fasfagxfasdfyfasfz`.split(/[xyz]/) //["fasfag", "fasdf", "fasf", ""]
還有一種排除性字元組
`xaxbycz`.split(/[^xyz]/) //["x", "x", "y", "z"]
或結構 |
例如c|d匹配或者d
/c|d/.test(`af`) // false
/c|d/.test(`ad`) // true
括號分組
(cd){1,} 可以匹配cdcd..等, 其中cd便是一個分組。
/(cd){1,}$/.test(`cdcd`) //true
貪婪模式和非貪婪模式
預設情況下,所有的限定詞都是貪婪模式,表示儘可能多的去捕獲字元。而在限定詞後增加“?”,則是非貪婪模式,表示儘可能少的去捕獲字元。
`ccccccd`.match(/c+/) //["ccccc"], 貪婪模式, 捕獲所有
`ccccccd`.match(/c+?/) //["c"], 非貪婪模式, 只捕獲到第一個
捕獲分組
在實際應用中我們很有可能需要獲取到匹配的字串,例如我們要將字串”萬里碧空飄著朵朵白雲”替換成”萬里碧空沒有一朵白雲”
"萬里碧空飄著朵朵白雲".replace(/(萬里碧空)飄著朵朵白雲/, `$1沒有一朵白雲`)
捕獲性分組會建立反向引用,js中可以通過 $+number 或者 “反斜槓”+number” 表示法進行引用。
注意:
反斜槓+number這種引用可以在正規表示式中使用,可用於匹配不同位置的相同子串,例如:
`www.bai.bai.com`.replace(/([a-z]+).1/, `$1`) // www.bai.com
非捕獲性分組
非捕獲性分組,通常由一對括號加上”?:”加上子表示式組成,非捕獲性分組不會建立反向引用,就好像沒有括號一樣。捕獲性分組和無捕獲性分組在搜尋效率方面也沒什麼不同,沒有哪一個比另一個更快。
/^(?:d+)/
正規表示式的方法
test
檢索字串中的指定子串,返回布林值
/^d[a-zA-Z]{3}$/.test(`1aac`) // true
exec
返回一個陣列,陣列中的第一個條目是第一個匹配
/^d[a-zA-Z]{3}$/.exec(`1aac`) // ["1aac"]
String可以使用正規表示式的方法
search
返回子串的開始位置
`a12b2334c34`.search(/d{4}/) // 4
match
返回匹配到的子串
`a12b2334c34`.match(/d{4}/) // ["2334"]
replace
替換匹配到的子串
`a12b2334c34`.replace(/d{4}/, `cccc`) // "a12bccccc34"
split
將字串分割成陣列
`a12b2334c34`.split(/d{4}/) // ["a12b", "c34"]
斷言
正向先行斷言 (?=exp)
代表字串中的一個位置,緊接該位置之後的字元序列能夠匹配 exp
/f(?=234)/.test(`123abcf234acd`) //true
負向先行斷言(?!exp)
代表字串中的一個位置,緊接該位置之後的字元序列不能匹配 exp
/f(?!234)/.test(`123abcf234acd`) //false
常用的正規表示式
Email 地址:
^w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*$
URl驗證
[a-zA-z]+://[^s]* 或 ^http://([w-]+.)+[w-]+(/[w-./?%&=]*)?$
密碼驗證
(?!^[0-9]+$)(?!^[A-z]+$)(?!^[^A-z0-9]+$)^[^su4e00-u9fa5]{6,16}$
郵編驗證
[1-9]d{5}(?!d)
手機號碼驗證
^1d{10}$
漢字驗證
^[u4e00-u9fa5]{0,}$