導(dǎo)讀
正則表達(dá)式是什么?有什么用?
正則表達(dá)式(Regular Expression)是一種文本規(guī)則,可以用來校驗(yàn)、查找、替換與規(guī)則匹配的文本。
又愛又恨的正則
正則表達(dá)式是一個強(qiáng)大的文本匹配工具,但是它的規(guī)則實(shí)在很繁瑣,而且理解起來也頗為蛋疼,容易讓人望而生畏。
如何學(xué)習(xí)正則
剛接觸正則時,我看了一堆正則的語義說明,但是仍然不明所以。后來,我多接觸一些正則的應(yīng)用實(shí)例,漸漸有了感覺,再結(jié)合語義說明,終有領(lǐng)悟。我覺得正則表達(dá)式和武俠修練武功差不多,應(yīng)該先練招式,再練心法。如果一開始就直接看正則的規(guī)則,保證你會懵逼。
當(dāng)你熟悉基本招式(正則基本使用案例)后,也該修煉修煉心法(正則語法)了。真正的高手不能只靠死記硬背那么幾招把式。就像張三豐教張無忌太極拳一樣,領(lǐng)悟心法,融會貫通,少俠你就可以無招勝有招,成為傳說中的絕世高手。
以上閑話可歸納為一句:學(xué)習(xí)正則應(yīng)該從實(shí)例去理解規(guī)則。

打開秘籍:欲練神功,必先自宮!沒有蛋,也就不會蛋疼了。
Java正則速成秘籍分三篇:
展示Java對于正則表達(dá)式的支持。
介紹正則表達(dá)式的語法規(guī)則。
從實(shí)戰(zhàn)出發(fā),介紹正則的常用案例。
本文是Java正則速成秘籍的最后一篇——見招拆招篇。
在 Java正則速成秘籍(一)之招式篇 和 Java正則速成秘籍(二)之心法篇,我們學(xué)習(xí)了Java支持正則功能的API以及正則表達(dá)式的語法。
本文則主要展示正則表達(dá)式在現(xiàn)實(shí)場景的應(yīng)用。文中不會再提及正則的語法以及Java正則相關(guān)的API,如有疑問,可以參考前面兩篇文章。
注:本文展示的案例,已經(jīng)經(jīng)過我的充分測試。如果你有興趣,可以參考 我的github單元測試源碼 。
正則應(yīng)用
雖然本系列洋洋灑灑的大談特談?wù)齽t表達(dá)式。但是我還是要在這里建議,如果一個正則表達(dá)式?jīng)]有經(jīng)過充分測試,還是要謹(jǐn)慎使用。
正則是把雙刃劍,它可以為你節(jié)省大量的代碼行。但是由于它不易閱讀,維護(hù)起來可是頭疼的哦(你需要一個字符一個字符的去理解)。
最實(shí)用的正則
校驗(yàn)中文
描述:校驗(yàn)字符串中只能有中文字符(不包括中文標(biāo)點(diǎn)符號)。中文字符的Unicode編碼范圍是\u4e00 到 \u9fa5。
如有興趣,可以參考百度百科-Unicode 。
^[\\u4e00-\\u9fa5]+$
匹配: 春眠不覺曉
不匹配:春眠不覺曉,
校驗(yàn)身份證號碼
描述:身份證為15位或18位。15位是第一代身份證。從1999年10月1日起,全國實(shí)行公民身份證號碼制度,居民身份證編號由原15位升至18位。
15位身份證
描述:由15位數(shù)字組成。排列順序從左至右依次為:六位數(shù)字地區(qū)碼;六位數(shù)字出生日期;三位順序號,其中15位男為單數(shù),女為雙數(shù)。
18位身份證
描述:由十七位數(shù)字本體碼和一位數(shù)字校驗(yàn)碼組成。排列順序從左至右依次為:六位數(shù)字地區(qū)碼;八位數(shù)字出生日期;三位數(shù)字順序碼和一位數(shù)字校驗(yàn)碼(也可能是X)。
身份證號含義詳情請見:百度百科-居民身份證號碼
地區(qū)碼(6位)
(1[1-5]|2[1-3]|3[1-7]|4[1-3]|5[0-4]|6[1-5])\\d{4}
出生日期(8位)
注:下面的是18位身份證的有效出生日期,如果是15位身份證,只要將第一個\d{4}改為\d{2}即可。
((\\d{4}((0[13578]|1[02])(0[1-9]|[12]\\d|3[01])|(0[13456789]|1[012])(0[1-9]|[12]\\d|30)|02(0[1-9]|1\\d|2[0-8])))|([02468][048]|[13579][26])0229)
15位有效身份證
^((1[1-5]|2[1-3]|3[1-7]|4[1-3]|5[0-4]|6[1-5])\\d{4})((\\d{2}((0[13578]|1[02])(0[1-9]|[12]\\d|3[01])|(0[13456789]|1[012])(0[1-9]|[12]\\d|30)|02(0[1-9]|1\\d|2[0-8])))|([02468][048]|[13579][26])0229)(\\d{3})$
匹配:110001700101031
不匹配:110001701501031
18位有效身份證
^((1[1-5]|2[1-3]|3[1-7]|4[1-3]|5[0-4]|6[1-5])\\d{4})((\\d{4}((0[13578]|1[02])(0[1-9]|[12]\\d|3[01])|(0[13456789]|1[012])(0[1-9]|[12]\\d|30)|02(0[1-9]|1\\d|2[0-8])))|([02468][048]|[13579][26])0229)(\\d{3}(\\d|X))$
匹配:110001199001010310 | 11000019900101015X
不匹配:990000199001010310 | 110001199013010310
校驗(yàn)有效用戶名、密碼
描述:長度為6-18個字符,允許輸入字母、數(shù)字、下劃線,首字符必須為字母。
^[a-zA-Z]\\w{5,17}$
匹配:he_llo123 | zhangsan | x007
不匹配:hello@worl_d.com | he&llo@world.co1 | .hello@wor#.co.uk
校驗(yàn)郵箱
描述:不允許使用IP作為域名,如 : hello@154.145.68.12
@符號前的郵箱用戶和.符號前的域名(domain)必須滿足以下條件:
- 字符只能是英文字母、數(shù)字、下劃線
_、.、-; - 首字符必須為字母或數(shù)字;
-
_、.、-不能連續(xù)出現(xiàn)。
域名的根域只能為字母,且至少為兩個字符。
^[A-Za-z0-9](([_\\.\\-]?[a-zA-Z0-9]+)*)@([A-Za-z0-9]+)(([\\.\\-]?[a-zA-Z0-9]+)*)\\.([A-Za-z]{2,})$
匹配:he_llo@worl.d.com | hel.l-o@wor-ld.museum | h1ello@123.com
不匹配:hello@worl_d.com | he&llo@world.co1 | .hello@wor#.co.uk
校驗(yàn)URL
描述:校驗(yàn)URL。支持http、https、ftp、ftps。
^(ht|f)(tp|tps)\\://[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,3})?(/\\S*)?$
匹配:http://google.com/help/me | http://www.google.com/help/me/ | https://www.google.com/help.asp | ftp://www.google.com | ftps://google.org
不匹配:http://un/www.google.com/index.asp
校驗(yàn)時間
描述:校驗(yàn)時間。時、分、秒必須是有效數(shù)字,如果數(shù)值不是兩位數(shù),十位需要補(bǔ)零。
^([0-1][0-9]|[2][0-3]):([0-5][0-9])$
匹配:00:00:00 | 23:59:59 | 17:06:30
不匹配:17:6:30 | 24:16:30
校驗(yàn)日期
描述:校驗(yàn)日期。日期滿足以下條件:
- 格式y(tǒng)yyy-MM-dd或yyyy-M-d
- 連字符可以沒有或是“-”、“/”、“.”之一
- 閏年的二月可以有29日;而平年不可以。
- 一、三、五、七、八、十、十二月為31日。四、六、九、十一月為30日。
^(?:(?!0000)[0-9]{4}([-/.]?)(?:(?:0?[1-9]|1[0-2])\\1(?:0?[1-9]|1[0-9]|2[0-8])|(?:0?[13-9]|1[0-2])\\1(?:29|30)|(?:0?[13578]|1[02])\\1(?:31))|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)([-/.]?)0?2\\2(?:29))$
匹配:2016/1/1 | 2016/01/01 | 20160101 | 2016-01-01 | 2016.01.01 | 2000-02-29
不匹配:2001-02-29 | 2016/12/32 | 2016/6/31 | 2016/13/1 | 2016/0/1
校驗(yàn)中國手機(jī)號碼
描述:中國手機(jī)號碼正確格式:11位數(shù)字。
移動有16個號段:134、135、136、137、138、139、147、150、151、152、157、158、159、182、187、188。其中147、157、188是3G號段,其他都是2G號段。
聯(lián)通有7種號段:130、131、132、155、156、185、186。其中186是3G(WCDMA)號段,其余為2G號段。
電信有4個號段:133、153、180、189。其中189是3G號段(CDMA2000),133號段主要用作無線網(wǎng)卡號。
總結(jié):13開頭手機(jī)號0-9;15開頭手機(jī)號0-3、5-9;18開頭手機(jī)號0、2、5-9。
此外,中國在國際上的區(qū)號為86,所以手機(jī)號開頭有+86、86也是合法的。
以上信息來源于 百度百科-手機(jī)號
^((\\+)?86\\s*)?((13[0-9])|(15([0-3]|[5-9]))|(18[0,2,5-9]))\\d{8}$
匹配:+86 18012345678 | 86 18012345678 | 15812345678
不匹配:15412345678 | 12912345678 | 180123456789
校驗(yàn)中國固話號碼
描述:固話號碼,必須加區(qū)號(以0開頭)。
3位有效區(qū)號:010、020~029,固話位數(shù)為8位。
4位有效區(qū)號:03xx開頭到09xx,固話位數(shù)為7。
如果想了解更詳細(xì)的信息,請參考 百度百科-電話區(qū)號 。
^(010|02[0-9])(\\s|-)\\d{8}|(0[3-9]\\d{2})(\\s|-)\\d{7}$
匹配:010-12345678 | 010 12345678 | 0512-1234567 | 0512 1234567
不匹配:1234567 | 12345678
校驗(yàn)IPv4地址
描述:IP地址是一個32位的二進(jìn)制數(shù),通常被分割為4個“8位二進(jìn)制數(shù)”(也就是4個字節(jié))。IP地址通常用“點(diǎn)分十進(jìn)制”表示成(a.b.c.d)的形式,其中,a,b,c,d都是0~255之間的十進(jìn)制整數(shù)。
^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])$
匹配:0.0.0.0 | 255.255.255.255 | 127.0.0.1
不匹配:10.10.10 | 10.10.10.256
校驗(yàn)IPv6地址
描述:IPv6的128位地址通常寫成8組,每組為四個十六進(jìn)制數(shù)的形式。
IPv6地址可以表示為以下形式:
- IPv6 地址
- 零壓縮 IPv6 地址(section 2.2 of rfc5952)
- 帶有本地鏈接區(qū)域索引的 IPv6 地址 (section 11 of rfc4007)
- 嵌入IPv4的 IPv6 地址(section 2 of rfc6052
- 映射IPv4的 IPv6 地址 (section 2.1 of rfc2765)
- 翻譯IPv4的 IPv6 地址 (section 2.1 of rfc2765)
顯然,IPv6地址的表示方式很復(fù)雜。你也可以參考
Stack overflow上的IPv6正則表達(dá)高票答案
(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))
匹配:1:2:3:4:5:6:7:8 | 1:: | 1::8 | 1::6:7:8 | 1::5:6:7:8 | 1::4:5:6:7:8 | 1::3:4:5:6:7:8 | ::2:3:4:5:6:7:8 | 1:2:3:4:5:6:7:: | 1:2:3:4:5:6::8 | 1:2:3:4:5::8 | 1:2:3:4::8 | 1:2:3::8 | 1:2::8 | 1::8 | ::8 | fe80::7:8%1 | ::255.255.255.255 | 2001:db8:3:4::192.0.2.33 | 64:ff9b::192.0.2.33
不匹配:1.2.3.4.5.6.7.8 | 1::2::3
特定字符
匹配長度為3的字符串:^.{3}$。
匹配由26個英文字母組成的字符串:^[A-Za-z]+$。
匹配由26個大寫英文字母組成的字符串:^[A-Z]+$。
匹配由26個小寫英文字母組成的字符串:^[a-z]+$。
匹配由數(shù)字和26個英文字母組成的字符串:^[A-Za-z0-9]+$。
匹配由數(shù)字、26個英文字母或者下劃線組成的字符串:^\\w+$。
特定數(shù)字
匹配正整數(shù):^[1-9]\\d*$
匹配負(fù)整數(shù):^-[1-9]\\d*$
匹配整數(shù):^(-?[1-9]\\d*)|0$
匹配正浮點(diǎn)數(shù):^[1-9]\\d*\\.\\d+|0\\.\\d+$
匹配負(fù)浮點(diǎn)數(shù):^-([1-9]\\d*\\.\\d*|0\\.\\d*[1-9]\\d*)$
匹配浮點(diǎn)數(shù):^-?([1-9]\\d*\\.\\d*|0\\.\\d*[1-9]\\d*|0?\\.0+|0)$