以前在程序中登陸或者校驗(yàn)也會(huì)經(jīng)常用正則,但是一般都是去網(wǎng)上找現(xiàn)成的,最近研究了一下,還是發(fā)現(xiàn)很博大精深的,而且,熟練了語(yǔ)法,的確非常方便,所以在這里總結(jié)推薦給大家。
為什么使用正則表達(dá)式
在工作中經(jīng)常會(huì)遇到這樣的情況,,比如我們需要驗(yàn)證輸入是不是一個(gè)座機(jī)電話,如010-1234567.如果不用正則表達(dá)式,怎么判斷呢?
看一下下面這個(gè)代碼:
private boolean isTel(String input){
if (input.length()!=11){
return false;
}
for (int i = 0; i<input.length();i++){
if (i==3){
if (input.charAt(i)!='-'){
return false;
}
}else {
if (!Character.isDigit(input.charAt(i))){
return false;
}
}
}
return true;
}
感覺(jué)有些麻煩,如果還要判定必須是010開(kāi)頭的或者01x開(kāi)頭的,豈不是更麻煩,這樣,使用正則表達(dá)式,就可以解決這個(gè)問(wèn)題。不僅僅是判斷電話,包括驗(yàn)證郵箱,驗(yàn)證網(wǎng)址,找到一個(gè)長(zhǎng)字符串中的固定字母位置等等,使用正則表達(dá)式都是很方便的。
用法
在介紹用法之前,需要知道正則表達(dá)式中的一些特殊符號(hào)代表什么,這個(gè)可以查詢文章結(jié)尾的附錄。
驗(yàn)證座機(jī)電話
既然說(shuō)到了是驗(yàn)證電話,那就先看看,座機(jī)號(hào)碼如何驗(yàn)證:
Pattern pattern;
Matcher matcher;
pattern = Pattern.compile("\\d\\d\\d[-]\\d\\d\\d\\d\\d\\d\\d");
matcher = pattern.matcher(result);
if (matcher.matches()){
show(matcher.group());
}else {
show("不是座機(jī)號(hào)碼");
}
其中result是輸入的字符串。
\d
代表的是數(shù)字,\d
前面還有一個(gè)\\
是為了轉(zhuǎn)義。
[]中的字符表示的是固定字符,在電話中固定字符就是-。
matcher.group()是將匹配結(jié)果輸出
手機(jī)號(hào)的驗(yàn)證
pattern = Pattern.compile("[1][3|7|8]\\d{9}");
matcher = pattern.matcher(result);
if (matcher.find()){
show(matcher.group());
}else {
show("不是手機(jī)號(hào)碼");
}
第一個(gè)[1]表示第一位是1,[3|7|8]表示第二位可以使3,7,8,\d{9}表示后面九位都是數(shù)字類型,所以用\d
郵箱驗(yàn)證
String regEx = "[a-zA-Z_]{1,}[a-zA-Z_0-9]{0,}@(([a-zA-Z0-9]){1,}\.){1,3}[a-zA-Z\-]{1,}";
pattern = Pattern.compile(regEx);
matcher = pattern.matcher(result);
if (matcher.find()){
show(matcher.group());
}else {
show("不是郵箱");
}
[a-zA-Z_]表示英文字母和下劃線,任意都可以。其中a-z這種寫(xiě)法,表示a-z任何字母,如果x-z就只能匹配xyz。
{1,}表示[a-zA-Z_]中所匹配的字母至少出現(xiàn)1次。連起來(lái)就表示,字符串要以字母或下劃線開(kāi)始,開(kāi)始的時(shí)候必須有1位字母哪怕f@163.com都是可以的。
字母之后是數(shù)字字母下劃線都可以了{(lán)0,}表示至少有0位,然后就是@符號(hào)。
(([a-zA-Z0-9]){1,}.)表示以任何字符開(kāi)始,至少有1個(gè),然后以.結(jié)尾的字符串,即xxx.類型的字符串,{1,3}至少有一個(gè),最多有3個(gè),為的是有些郵箱是@vip.163.xxx,這樣的就會(huì)有兩個(gè)xxx.
最后以[a-zA-Z-]{1,}結(jié)尾,表示最后的.后面還要接一個(gè)字符串,可能是com可能是net
部分匹配與嚴(yán)格匹配
好吧,我不知道該如何形容這個(gè)概念,我在學(xué)習(xí)這塊的時(shí)候,一直不明白的一個(gè)問(wèn)題,就是正則表達(dá)式,可以校驗(yàn)一個(gè)字符串,但是有兩種情況:
1.比如我希望字符串中有手機(jī)號(hào),然后我用正則可以取到字符串那么這個(gè)字符串是“手機(jī)號(hào):136xxxxxxxx”都是可以的,也就是,前面有部分中文,是不影響的,我只取出我要的。
2.比如我希望嚴(yán)格匹配,也就是“手機(jī)號(hào):136xxxxxxxx”是不行的,必須要“136xxxxxxxx”不能帶有其他字符。
這種情況我的想法是依靠^和$。
- 在[a-z]里面表示取反,也就是匹配不再a-z中的符號(hào)字母,但是如果放在開(kāi)頭可以標(biāo)識(shí)以xxx開(kāi)頭。
- $表示以xxx結(jié)尾
還是以上面的手機(jī)號(hào)的做為例子,我們的正則表達(dá)式是"[1][3|7|8]\\d{9}"
那么我們匹配"tel is 136xxxxxxxx"也是可以匹配到的,現(xiàn)在我們改一下匹配規(guī)則:"^[1][3|7|8]\\d{9}$"
,這時(shí)就不能再匹配"tel is 136xxxxxxxx"了,只能匹配"136xxxxxxxx"
分割
pattern = Pattern.compile("[,|]+");
String[] strs = pattern.split("hello,Hello android,hello deep,,android|Google");
for (int i=0;i<strs.length;i++) {
Log.e("deep","strs="+strs[i]);
}
輸出結(jié)果是:
05-11 11:49:30.473 30824 30824 E deep : strs=hello
05-11 11:49:30.473 30824 30824 E deep : strs=Hello android
05-11 11:49:30.473 30824 30824 E deep : strs=hello deep
05-11 11:49:30.475 30824 30824 E deep : strs=android
05-11 11:49:30.475 30824 30824 E deep : strs=Google
"[,|]+"
中+是以前面的字符至少一個(gè)進(jìn)行匹配,[,|]是以,或|進(jìn)行匹配,所以匹配到字符串中就是,或,,或|。
由于用的是split方法,所以就是以匹配的字符進(jìn)行分割,分割結(jié)果如log所示
替換
單個(gè)替換
pattern = Pattern.compile("android");
matcher = pattern.matcher("android Hello World,android Hello World");
Log.e("deep",matcher.replaceFirst("deep"));
結(jié)果如下:
05-11 13:36:03.285 23098 23098 E deep : deep Hello World,android Hello World
matcher.replaceFirst只替換了匹配到的第一個(gè)
全部替換
pattern = Pattern.compile("android");
matcher = pattern.matcher("android Hello World,android Hello World");
Log.e("deep",matcher.replaceAll("deep"));
結(jié)果如下:
05-11 13:38:09.739 24160 24160 E deep : deep Hello World,deep Hello World
matcher.replaceAll替換了匹配到的所有android
appendReplacement
pattern = Pattern.compile("android");
matcher = pattern.matcher("android Hello World,android Hello World ");
StringBuffer sbr = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(sbr, "deep");
}
matcher.appendTail(sbr);
Log.e("deep",sbr.toString());
結(jié)果如下:
05-11 13:38:09.739 24160 24160 E deep : deep Hello World,deep Hello World
appendReplacement是逐段匹配替換添加到緩沖區(qū)
附錄
附錄中內(nèi)容摘自網(wǎng)絡(luò)不同文章,我只是把他們粘貼在了一起。
語(yǔ)法
語(yǔ)法 | 用處 |
---|---|
\ | 轉(zhuǎn)移符:將下一個(gè)字符標(biāo)記符、或一個(gè)向后引用、或一個(gè)八進(jìn)制轉(zhuǎn)義符。例如,“\n”匹配\n。“\n”匹配換行符。序列“\”匹配“\”而“(”則匹配“(”。 |
^ | 匹配輸入字符串的開(kāi)始位置。如果設(shè)置了RegExp對(duì)象的Multiline屬性,^也匹配“\n”或“\r”之后的位置。 |
$ | 匹配輸入字符串的結(jié)束位置。如果設(shè)置了RegExp對(duì)象的Multiline屬性,^也匹配“\n”或“\r”之后的位置。 |
* | 匹配前面的子表達(dá)式任意次。例如,zo能匹配“z”,“zo”以及“zoo”。等價(jià)于{0,}。 |
+ | 匹配前面的子表達(dá)式一次或多次(大于等于1次)。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等價(jià)于{1,}。 |
? | 匹配前面的子表達(dá)式零次或一次。例如,“do(es)?”可以匹配“do”或“does”中的“do”。?等價(jià)于{0,1}。 |
{n} | n是一個(gè)非負(fù)整數(shù)。匹配確定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的兩個(gè)o。 |
{n,} | n是一個(gè)非負(fù)整數(shù)。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等價(jià)于“o+”。“o{0,}”則等價(jià)于“o*”。 |
{n,m} | m和n均為非負(fù)整數(shù),其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”將匹配“fooooood”中的前三個(gè)o。“o{0,1}”等價(jià)于“o?”。請(qǐng)注意在逗號(hào)和兩個(gè)數(shù)之間不能有空格。 |
? | 當(dāng)該字符緊跟在任何一個(gè)其他限制符(*,+,?,{n},{n,},{n,m})后面時(shí),匹配模式是非貪婪的。非貪婪模式盡可能少的匹配所搜索的字符串,而默認(rèn)的貪婪模式則盡可能多的匹配所搜索的字符串。例如,對(duì)于字符串“oooo”,“o+?”將匹配單個(gè)“o”,而“o+”將匹配所有“o”。 |
.點(diǎn) | 匹配除“\r\n”之外的任何單個(gè)字符。要匹配包括“\r\n”在內(nèi)的任何字符,請(qǐng)使用像“[\s\S]”的模式。 |
^[\u0391-\uFFE5]+$ | 一個(gè)或多個(gè)漢字 |
x(豎線)y | 匹配x或y。例如,“z(豎線)food”能匹配“z”或“food”或"zood"(此處請(qǐng)謹(jǐn)慎)。“(z(豎線)f)ood”則匹配“zood”或“food”。 |
[xyz] | 字符集合。匹配所包含的任意一個(gè)字符。例如,“[abc]”可以匹配“plain”中的“a”。 |
[^xyz] | 負(fù)值字符集合。匹配未包含的任意字符。例如,“[^abc]”可以匹配“plain”中的“plin”。 |
[a-z] | 字符范圍。匹配指定范圍內(nèi)的任意字符。例如,“[a-z]”可以匹配“a”到“z”范圍內(nèi)的任意小寫(xiě)字母字符。注意:只有連字符在字符組內(nèi)部時(shí),并且出現(xiàn)在兩個(gè)字符之間時(shí),才能表示字符的范圍; 如果出字符組的開(kāi)頭,則只能表示連字符本身. |
[^a-z] | 負(fù)值字符范圍。匹配任何不在指定范圍內(nèi)的任意字符。例如,“[^a-z]”可以匹配任何不在“a”到“z”范圍內(nèi)的任意字符。 |
\b | 匹配一個(gè)單詞邊界,也就是指單詞和空格間的位置(即正則表達(dá)式的“匹配”有兩種概念,一種是匹配字符,一種是匹配位置,這里的\b就是匹配位置的)。例如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”。 |
\B | 匹配非單詞邊界。“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”。 |
\cx | 匹配由x指明的控制字符。例如,\cM匹配一個(gè)Control-M或回車符。x的值必須為A-Z或a-z之一。否則,將c視為一個(gè)原義的“c”字符。 |
\d | 匹配一個(gè)數(shù)字字符。等價(jià)于[0-9]。 |
\D | 匹配一個(gè)非數(shù)字字符。等價(jià)于[^0-9]。 |
\f | 匹配一個(gè)換頁(yè)符。等價(jià)于\x0c和\cL。 |
\n | 匹配一個(gè)換行符。等價(jià)于\x0a和\cJ。 |
\r | 匹配一個(gè)回車符。等價(jià)于\x0d和\cM。 |
\s | 匹配任何不可見(jiàn)字符,包括空格、制表符、換頁(yè)符等等。等價(jià)于[ \f\n\r\t\v]。 |
\S | 匹配任何可見(jiàn)字符。等價(jià)于[^ \f\n\r\t\v]。 |
\t | 匹配一個(gè)制表符。等價(jià)于\x09和\cI。 |
\v | 匹配一個(gè)垂直制表符。等價(jià)于\x0b和\cK。 |
\w | 匹配包括下劃線的任何單詞字符。類似但不等價(jià)于“[A-Za-z0-9_]”,這里的"單詞"字符使用Unicode字符集。 |
\W | 匹配任何非單詞字符。等價(jià)于“[^A-Za-z0-9_]”。 |
\xn | 匹配n,其中n為十六進(jìn)制轉(zhuǎn)義值。十六進(jìn)制轉(zhuǎn)義值必須為確定的兩個(gè)數(shù)字長(zhǎng)。例如,“\x41”匹配“A”。“\x041”則等價(jià)于“\x04&1”。正則表達(dá)式中可以使用ASCII編碼。 |
\num | 匹配num,其中num是一個(gè)正整數(shù)。對(duì)所獲取的匹配的引用。例如,“(.)\1”匹配兩個(gè)連續(xù)的相同字符。 |
\n | 標(biāo)識(shí)一個(gè)八進(jìn)制轉(zhuǎn)義值或一個(gè)向后引用。如果\n之前至少n個(gè)獲取的子表達(dá)式,則n為向后引用。否則,如果n為八進(jìn)制數(shù)字(0-7),則n為一個(gè)八進(jìn)制轉(zhuǎn)義值。 |
\nm | 標(biāo)識(shí)一個(gè)八進(jìn)制轉(zhuǎn)義值或一個(gè)向后引用。如果\nm之前至少有nm個(gè)獲得子表達(dá)式,則nm為向后引用。如果\nm之前至少有n個(gè)獲取,則n為一個(gè)后跟文字m的向后引用。如果前面的條件都不滿足,若n和m均為八進(jìn)制數(shù)字(0-7),則\nm將匹配八進(jìn)制轉(zhuǎn)義值nm。 |
\nml | 如果n為八進(jìn)制數(shù)字(0-7),且m和l均為八進(jìn)制數(shù)字(0-7),則匹配八進(jìn)制轉(zhuǎn)義值nml。 |
\un | 匹配n,其中n是一個(gè)用四個(gè)十六進(jìn)制數(shù)字表示的Unicode字符。例如,\u00A9匹配版權(quán)符號(hào)(\?)。 |
< \> | 匹配詞(word)的開(kāi)始(\<)和結(jié)束(\>)。例如正則表達(dá)式\<the>能夠匹配字符串"for the wise"中的"the",但是不能匹配字符串"otherwise"中的"the"。注意:這個(gè)元字符不是所有的軟件都支持的。 |
+ | 匹配1或多個(gè)正好在它之前的那個(gè)字符。例如正則表達(dá)式9+匹配9、99、999等。注意:這個(gè)元字符不是所有的軟件都支持的。 |
? | 匹配0或1個(gè)正好在它之前的那個(gè)字符。注意:這個(gè)元字符不是所有的軟件都支持的。 |
{i} {i,j} | 匹配指定數(shù)目的字符,這些字符是在它之前的表達(dá)式定義的。例如正則表達(dá)式A[0-9]{3} 能夠匹配字符"A"后面跟著正好3個(gè)數(shù)字字符的串,例如A123、A348等,但是不匹配A1234。而正則表達(dá)式[0-9]{4,6} 匹配連續(xù)的任意4個(gè)、5個(gè)或者6個(gè)數(shù)字 |
flag的取值范圍
這里不再詳細(xì)描述了,因?yàn)槲疫€沒(méi)有遇到過(guò)需要設(shè)置這些flag的情況,但是還是在這里總結(jié)給大家。
在使用Pattern.compile函數(shù)時(shí),可以加入控制正則表達(dá)式的匹配行為的參數(shù):
Pattern Pattern.compile(String regex, int flag)
- Pattern.CANON_EQ 當(dāng)且僅當(dāng)兩個(gè)字符的"正規(guī)分解(canonical decomposition)"都完全相同的情況下,才認(rèn)定匹配。比如用了這個(gè)標(biāo)志之后,表達(dá)式"a/u030A"會(huì)匹配"?"。默認(rèn)情況下,不考慮"規(guī) 范相等性(canonical equivalence)"。
- Pattern.CASE_INSENSITIVE 默認(rèn)情況下,大小寫(xiě)不明感的匹配只適用于US-ASCII字符集。這個(gè)標(biāo)志能讓表達(dá)式忽略大小寫(xiě)進(jìn)行匹配。要想對(duì)Unicode字符進(jìn)行大小不明感的匹 配,只要將UNICODE_CASE與這個(gè)標(biāo)志合起來(lái)就行了。
Pattern.COMMENTS 在這種模式下,匹配時(shí)會(huì)忽略(正則表達(dá)式里的)空格字符(譯者注:不是指表達(dá)式里的"http://s",而是指表達(dá)式里的空格,tab,回車之類)。注釋從#開(kāi)始,一直到這行結(jié)束。可以通過(guò)嵌入式的標(biāo)志來(lái)啟用Unix行模式。 - Pattern.DOTALL 在這種模式下,表達(dá)式'.'可以匹配任意字符,包括表示一行的結(jié)束符。默認(rèn)情況下,表達(dá)式'.'不匹配行的結(jié)束符。
- Pattern.MULTILINE
在這種模式下,''和'$'分別匹配一行的開(kāi)始和結(jié)束。此外,''仍然匹配字符串的開(kāi)始,'$'也匹配字符串的結(jié)束。默認(rèn)情況下,這兩個(gè)表達(dá)式僅僅匹配字符串的開(kāi)始和結(jié)束。 - Pattern.UNICODE_CASE
在這個(gè)模式下,如果你還啟用了CASE_INSENSITIVE標(biāo)志,那么它會(huì)對(duì)Unicode字符進(jìn)行大小寫(xiě)不明感的匹配。默認(rèn)情況下,大小寫(xiě)不敏感的匹配只適用于US-ASCII字符集。 - Pattern.UNIX_LINES 在這個(gè)模式下,只有'/n'才被認(rèn)作一行的中止,并且與'.','^',以及'$'進(jìn)行匹配。