一看就懂的正則表達(dá)式教程
案例引入
在講正則表達(dá)式前,我們不妨先從一個(gè)場(chǎng)景來(lái)逐漸引入。
你可能有過(guò)這樣的經(jīng)歷:我們?nèi)ツ承┚W(wǎng)站注冊(cè)帳號(hào),當(dāng)你在設(shè)置密碼的時(shí)候,網(wǎng)站會(huì)提示你密碼的長(zhǎng)度范圍,以及對(duì)應(yīng)的規(guī)則限制(如下圖)。
根據(jù)上圖,我們將密碼設(shè)置規(guī)則可以描述為兩個(gè)條件:
(1)長(zhǎng)度為6-16位;
(2)密碼中必須包含數(shù)字,大寫字母,小寫字母,特殊字符(指定字符);
現(xiàn)在假設(shè)我們不知道正則表達(dá)式,作為程序員的你,該如何去實(shí)現(xiàn)這樣一個(gè)密碼驗(yàn)證呢?
下面是我寫的一個(gè)校驗(yàn)方法(樣本):
/** * 校驗(yàn)用戶密碼是否滿足設(shè)置規(guī)則 * * @param password 用戶輸入的密碼 * @return true-滿足;false-不滿足 */ public static boolean checkPassword(String password) { // 密碼不能為空 if (password == null || password.isEmpty()) { return false; } // 校驗(yàn)密碼長(zhǎng)度(6-16位) int len = password.length(); if (len < 6 || len > 16) { return false; } // 定義四種組合條件 boolean hasNumber = false; boolean hasSmallLetter = false; boolean hasBigLetter = false; boolean hasSpecialChar = false; // 將密碼字符串拆分為單個(gè)字符,然后對(duì)每個(gè)字符進(jìn)行校驗(yàn) char[] chars = password.toCharArray(); for (char c : chars) { // 是否包含數(shù)字0-9 if (c >= '0' && c <= '9') { hasNumber = true; continue; } // 是否包含小寫字母a-z if (c >= 'a' && c <= 'z') { hasSmallLetter = true; continue; } // 是否包含大寫字母A-Z if (c >= 'A' && c <= 'Z') { hasBigLetter = true; continue; } // 是否滿足指定的特殊字符 if ("~@#S%*_-+=:.?".indexOf(c) > 0) { hasSpecialChar = true; continue; } // 如果某個(gè)字符不在上面四種情況,則不滿足規(guī)則 return false; } // 如果四種組合條件均滿足,則符合密碼設(shè)置規(guī)則 return hasNumber && hasSmallLetter && hasBigLetter && hasSpecialChar; }
這個(gè)方法寫得對(duì)不對(duì)呢?我們不防用幾組密碼去進(jìn)行驗(yàn)證下:
可以看到,我們列舉的8組密碼,都得到了驗(yàn)證,說(shuō)明我們的方法是OK的。
但這樣一個(gè)密碼設(shè)置規(guī)則校驗(yàn),我們就差不多寫近 30 行的代碼,是不是感覺(jué)有點(diǎn)累贅了呢?明明規(guī)則很簡(jiǎn)單,代碼量卻寫了這么多,有沒(méi)有什么方法可以簡(jiǎn)化我們的代碼呢?當(dāng)然有!于是,這時(shí)就可以讓我們今天的主角正則表達(dá)式出場(chǎng)了。
下面,則是具有相同校驗(yàn)功能,基于正則表達(dá)式的驗(yàn)證方法:
/** * 通過(guò)正則表達(dá)式校驗(yàn)用戶密碼是否滿足設(shè)置規(guī)則 * * @param password 用戶輸入的密碼 * @return true-滿足;false-不滿足 */ public static boolean checkPasswordByRegex(String password) { return Pattern.matches("^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[~@#S%*_\\-+=:.?])[A-Za-z0-9~@#S%*_\\-+=:.?]{8,20}$", password); }
那么它寫得到底對(duì)不對(duì)呢?于是,我們可以通過(guò)上面的示例數(shù)據(jù),繼續(xù)調(diào)用該方法來(lái)進(jìn)行驗(yàn)證:
通過(guò)結(jié)果我們可以看到,他也是符合我們預(yù)期的。于是我們發(fā)現(xiàn),在不用正則表達(dá)式的時(shí)候,我們的代碼量近30行,而使用了正則表達(dá)式,代碼就濃縮為了1行,也就是說(shuō),使用正則表達(dá)式時(shí)可以簡(jiǎn)化我們的代碼。
但同時(shí)我們也可知,正則表達(dá)式具有一定的學(xué)習(xí)成本,如果你不懂正則表達(dá)式,那么你看它可能就是一頭霧水,如果出了問(wèn)題,更也就無(wú)從下手去修改它了。
所以,學(xué)會(huì)正則表達(dá)式還是有必要的,至少以后你的同事寫出來(lái)后,不會(huì)在腦子里出現(xiàn) "這是寫的啥玩意兒???怎么我看不懂" 的想法。
正則表達(dá)式
什么是正則表達(dá)式?通過(guò)上面的案例大家可能多少有點(diǎn)了解了。是的,他就是通過(guò)一行字符串,來(lái)描述一定的規(guī)則(如下圖箭頭所指紅框處)。
命名規(guī)范
正則表達(dá)式的英文為 Regular Expression,所以我們通常采用這兩個(gè)單詞的首幾個(gè)字母合在一起,把正則表達(dá)式相關(guān)的變量名定義為 regexp(單數(shù)) 或 regexps(復(fù)數(shù)) 。
比如:
又比如,在 Java 的 String 類中,有幾個(gè)相關(guān)替換的方法,它也是支持正則表達(dá)式的,他的參數(shù)命名也是 regex 。
結(jié)構(gòu)組成
正則表達(dá)式通常由一些普通字符,以及一些元字符組成。
普通字符:就是本身作為一個(gè)字符時(shí),它不具有其他含義,像我們常用的大小寫字母和數(shù)字。
元字符:就是除了本身作為一個(gè)字符外,他還可以表達(dá)其他含義(下圖是部分元字符節(jié)選)。
其實(shí),我們學(xué)習(xí)正則表達(dá)式,大部分就是基于元字符的學(xué)習(xí)。
用途場(chǎng)景
學(xué)習(xí)了正則表達(dá)式,我們可以有哪些用途場(chǎng)景呢?
(1)做字符串的規(guī)則驗(yàn)證(比如前面的案例引入中,我們可以通過(guò)正則表達(dá)式來(lái)驗(yàn)證一個(gè)密碼是否符合規(guī)則)。
(2)做字符串的替換(比如將一個(gè)字符串中所有的大小寫字母去掉,或者替換為指定符號(hào))。
(3)提取字符串中所需要的字符(比如一個(gè)字符串中所有的數(shù)字提取出來(lái),組成一個(gè)新的字符串)。
Java中的正則校驗(yàn)
正則表達(dá)式主要用途就是校驗(yàn)字符串,那么在Java中,只需要通過(guò)下面這個(gè)方法即可進(jìn)行校驗(yàn)。
boolean result = Pattern.matches(regex, input);
其中:
regex 是我們需要寫的正則表達(dá)式校驗(yàn)規(guī)則;
input 是我們待校驗(yàn)的字符串;
返回的 result 就是我們校驗(yàn)的結(jié)果,當(dāng)為 true 的時(shí)候,表示校驗(yàn)通過(guò),當(dāng)為 false 的時(shí)候,則表示校驗(yàn)不通過(guò)。
正則元字符
正則:普通字符
當(dāng)我們的正則表達(dá)式為一串普通字符(不包含元字符)時(shí),校驗(yàn)字符串只有和正則一致時(shí),才會(huì)校驗(yàn)通過(guò)。
具體效果如下:
說(shuō)明:后面例子為節(jié)省篇幅,不顯得累贅,就不再貼代碼,只貼校驗(yàn)結(jié)果。
正則:\d
\d 表示一個(gè)數(shù)字。
如:
aaa\d: 表示驗(yàn)證的字符串后面必須以 aaa 開(kāi)頭,且以一個(gè)數(shù)字結(jié)尾。
aaa\dbbb:aaa和bbb中間有一個(gè)數(shù)字
aaa\d\d:aaa后面跟2個(gè)數(shù)字
注意:在Java定義的正則里,由于一個(gè)\表示的是字符串轉(zhuǎn)義,因此在Java定義帶有\(zhòng)的元字符時(shí),還需要多寫一個(gè)\,即\\,至于其他語(yǔ)言,自己可查閱相關(guān)資料進(jìn)行了解。
正則:\D
\D 表示一個(gè)非數(shù)字,它和上面 \d 的意思恰好相反。
如:
\D\D\D: 則表示一個(gè)長(zhǎng)度為3,不包含數(shù)字的字符串。
111\D222:則表示111和222中間,必須包含一個(gè)非數(shù)字。
正則:\w
\w 表示一個(gè)字母(大小寫均可)、數(shù)字,或下劃線。
如:
12\w45:則表示12和45中間必須是一個(gè)字母,數(shù)字,或下劃線。
正則:\W
\W 與 \w 相反,表示這個(gè)位置的字符既不是字母、數(shù)字,也不是下劃線。
也就是:特殊符號(hào)(除下劃線),或者空格等滿足。
如:
12\w45:則表示12和45中間是一個(gè)非字母,非數(shù)字,或非下劃線。
正則:\s
\s 表示匹配一個(gè)看不見(jiàn)的符號(hào),即空格或制表符(Tab鍵)
如:
88\s99:則表示88和99中間須是一個(gè)空格或制表符。
(由于我的編輯器設(shè)置了1個(gè)制表符替換為4個(gè)空格,所以這里就不列舉制表符情況了)
正則:\S
\S 與 \s 相反,表示一個(gè)可以看得見(jiàn)的符號(hào)。
如:
88\S99:則表示88和99中間須有一個(gè)看得見(jiàn)的符號(hào)。
正則:.
. (小數(shù)點(diǎn)) 則表示“\n”和"\r"之外的任何單個(gè)字符。
如:
.... :則表示任意四個(gè)字符
正則:|
| (豎線) 則表示或的關(guān)系,表示檢測(cè)的字符串須滿足其中一個(gè)時(shí),才符合條件。
如:
aa|bb|cc:則表示輸入的字符串須是aa,或bb,或cc其中的一個(gè)。
注意,如果我們或者關(guān)系的前后還有其它字符時(shí),需要用()將他們包裹起來(lái)。
如:
xx(aa|bb|cc)yy:則表示輸入的字符串須是xx開(kāi)頭,yy結(jié)尾,且中間是aa,或bb,或cc其中的一個(gè)。
正則:[abc]
[ ] 表示匹配其中任意一個(gè)字符。
如:
a[bcd]e:則表示a和e的中間須是b,或c,或d其中的一個(gè)
注意:用 | 表示其中之一,他可以是字符,也可以是字符串。而只用中括號(hào)時(shí),則只表示其中一個(gè)字符。
正則:[^abc]
[^ ] 表示不與中括號(hào)里的任意字符匹配。
如:
a[^bcd]e:則表示a和e的中間除b,c,d這三個(gè)字符外,其他的字符都滿足。
正則:[a-z]
[值1-值2] 則表示值1到值2中間的所有字符都滿足(包括值1和值2)。常用該正則來(lái)表示大小寫字母范圍,數(shù)字范圍。
如:
a[b-d]e:等同于 a[bcd]e,因?yàn)?b-d 其實(shí)就是b,c,d三個(gè)數(shù)。
a[0-9]e:則表示a和e中間是一個(gè)數(shù)字,等同于 a\de(前面說(shuō)過(guò)\d表示一個(gè)數(shù)字)
正則:[^a-z]
[^值1-值2] 則表示除值1和值2之外的所有字符,都可以滿足。
如:
a[^1-3]e:則表示a和e中間的字符,只要不是1,2,3,則都滿足。
正則:\num
這里的num指number,也就是數(shù)字,當(dāng)\后面跟數(shù)字,表示匹配第幾個(gè)括號(hào)中的結(jié)果。
比如:現(xiàn)在有 abcd 字符串,當(dāng)我們用小括號(hào)把 c 包裹起來(lái)后,然后在字符串后面寫上 \1,即 ab(c)d\1,則這里的 \1 就指 c,因?yàn)?\1 表示第1個(gè)小括號(hào)中的結(jié)果。
ab(c)d\1:等同于 abcdc 。
如果我們繼續(xù)把 ab(c)d\1 中的 d 包括起來(lái),并在后面寫上 \2,即 ab(c)(d)\1\2, 那么這里的 \2 就表示 d 這個(gè)字符,因?yàn)榈?個(gè)小括號(hào)的結(jié)果是 d,所以整個(gè)表達(dá)式就等同于 abcdcd 。
ab(c)(d)\1\2:等同于 abcdcd,也等同于 ab(cd)\1 。
正則:?
? 表示匹配前面的子表達(dá)式零次或一次。
如:
abc?de: 表示可匹配的字符串為 abde (匹配0次c) 或 abcde (匹配1次c)。
正則:+
匹配前面的子表達(dá)式一次或多次 (次數(shù) >= 1,即至少1次)
如:
abc+de:ab 和 de 之前至少有一個(gè) c 。
正則:{n}
這里的 n 是一個(gè)非負(fù)整數(shù)。匹配確定的前面的子表達(dá)式 n 次。
如:
abc{3}de:表示 ab 和 de 之間有3個(gè)c。
ab(xx|yy){3}de:表示 ab 和 de 之間有 xx 或 yy 的個(gè)數(shù), 一起合計(jì)為3個(gè)。
正則:{n,m}
m和n均為非負(fù)整數(shù),其中 n<=m。最少匹配 n 次且最多匹配 m 次。
如:
abc{2,3}de:表示 ab 和 de 之間有 2 到 3 個(gè) c。
正則:*
表示匹配前面的子表達(dá)式任意次。
如:
abc*de:表示 ab 和 de 之間有任意個(gè)數(shù)(包括0)c 。
總結(jié)
到此這篇關(guān)于正則表達(dá)式教程的文章就介紹到這了,更多相關(guān)一看就懂正則表達(dá)式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
dw(dreamweaver)正則表達(dá)式函數(shù)列表
dw(dreamweaver)正則表達(dá)式函數(shù)列表,需要的朋友可以參考下。2007-12-12詳解正則表達(dá)式后面不要包含指定的字符串內(nèi)容
這篇文章主要介紹了正則表達(dá)式后面不要包含指定的字符串內(nèi)容的相關(guān)知識(shí),非常不錯(cuò),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2019-04-04Java正則表達(dá)式過(guò)濾出字母、數(shù)字和中文
正則表達(dá)式在java程序中應(yīng)用非常廣泛,本文給大家介紹java正則表達(dá)式過(guò)濾字母、數(shù)字和中文,本文代碼講解的非常詳細(xì),非常具有參考價(jià)值,感興趣的朋友快來(lái)看看吧2015-10-10JavaScript正則表達(dá)式驗(yàn)證代碼(推薦)
這篇文章主要介紹了JavaScript正則表達(dá)式驗(yàn)證的相關(guān)知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值,感興趣的朋友一起看看吧2016-05-05vbs:一段比較精簡(jiǎn)的代碼實(shí)現(xiàn)取得字符串的"字節(jié)"數(shù)
vbs:一段比較精簡(jiǎn)的代碼實(shí)現(xiàn)取得字符串的"字節(jié)"數(shù)...2007-04-04