iOS開發(fā)-正則表達式

轉自:Sindri的小巢

原文鏈接:http://www.lxweimin.com/p/00da4d87b777?

正則表達式是一種用來進行文本匹配的工具,其語法優(yōu)美簡潔。在開發(fā)中,查找、對比以及匹配字符串是家常便飯的業(yè)務,通過正則表達式我們將這些業(yè)務描述成某些需求規(guī)則,來讓我們的代碼更美觀、實用。例如我們要驗證用戶輸入的密碼長度是否滿足6~18位的長度,新手最常見的驗證方式是判斷輸入的密碼長度。

return (textField.text.length >= 6 && textField.text.leng <= 18);

盡管這種判斷方式?jīng)]有任何問題,而上面的驗證換做正則表達式的匹配字符就顯得短小精悍

^.{6,18}$

還有,大部分的固定電話都是0區(qū)號-八位數(shù)字的格式,那么正則表達式的匹配如下

^0\\d{2}\-?\\d{8}$

再比如,對于密碼強度的認證。如今的密碼應該包括一個或以上的大寫字母以及小寫字母,對此正則表達式的匹配是

(^.*[A-Z]+.*[a-z]+.*$|^.*[a-z]+.*[A-Z]+.*$)

表達式字符解析

如果是新手開發(fā)者,那么很有可能不理解上面的正則表達式。那么我們先看第一個匹配條件,匹配6-18位的密碼長度。根據(jù)題目的要求,就能夠輕易的判斷出{6,18}表示6-18位。其中,{n}匹配字符重復n次;{n,}匹配重復n次或更多次;{n,m}匹配重復n到m之間次數(shù)。

那么讀者對^、.和$三個符號可能不明所以。^和$屬于特殊符號,前者表示匹配字符串的開頭,后者表示匹配字符串的結尾。由于我們有時需要在一段很長的字符串中匹配某些小片段字符串時(比如在圖文混編中匹配長字符串中留空的表情符號),適當使用這兩個符號可以減少匹配次數(shù),提高執(zhí)行效率。

那么結合這幾個字符代表含義,可以得出.符號表示任一字符(除換行符之外)。那么還可以得出{6,18}這個特殊符號表示的是前一個符號代表的位數(shù)。結合起來說^.{6,18}$匹配一段6至18位長度的字符串,所以可以用來驗證密碼長度。

當然了,.字符的匹配率太高,更多時候我們需要匹配的是具體到數(shù)字或者字母,甚至準確的數(shù)字和字母。那么除了.字符以外,還有\(zhòng)d用來表示任意的單個數(shù)字,\w表示任意一個字母或數(shù)字或者直接使用0-9的任意數(shù)字表示具體數(shù)字。而特殊符號?表示前一個字符為0或者1個。

所以上面的^0\\d{2}\-?\\d{8}$匹配了以數(shù)字0開頭,接著兩個數(shù)字,后面跟著-號跟八個數(shù)字,然后結尾的字符串,不管是010-88888888,還是02098989898都能進行正確匹配。

最后的一個表達式可能是最復雜的表達式,根據(jù)上面對部分符號的解析。我們可以把

^.*[A-Z]+.*[a-z]+.*$|^.*[a-z]+.*[A-Z]+.*$

拆分成

^.*[A-Z]+.*[a-z]+.*$ 跟 ^.*[a-z]+.*[A-Z]+.*$

這兩個單獨的表達式,而中間的|不難猜到就是邏輯的或。我們將對前一個進行拆分,來一步步識別這個表達式的匹配規(guī)則。這里教大家我拆分表達式的方法:我把表達式的字符分為兩類:值表達和修飾表達。所謂值表達就是說這個符號表示了某個值,就像\d表示數(shù)字,.表示任意非換行符字符。修飾表達用來修飾值達成某種條件,比如{2}表示前面一個值重復兩次,*表示前一個值重復0次或者更多次。根據(jù)這種方法,那么^.*[A-Z]+.*[a-z]+.*$可以拆分成部分:^$、 .* 、 [A-Z]+ 、 [a-z]+。

^$就不再多說。

.*這里要介紹的就是*表示前一個值符號重復任意次數(shù)。

[A-Z]+中-表示從左邊的值到右邊的值之間所有值形成的閉集合;[]方括號表示的值必須是括號中間集合的子集,要注意的是括號里面可以有多個集合,比如[A-Z0-9a-z]表示匹配任意一個大小寫字母或數(shù)字;+同*有點像,但是+表示的是至少一個的重復值。

結合上面的解析,那么^.*[A-Z]+.*[a-z]+.*$表示以任意數(shù)量的字符開頭,然后跟著一個大寫字母,大寫字母后面有任意數(shù)量的字符以及一個小寫字母,然后又是任意數(shù)量的數(shù)字、字母或者字符。而^.*[a-z]+.*[A-Z]+.*$表示小寫字母在大寫字母前面任意數(shù)量的字符的位置,兩個結合匹配可以確保字符串中包括至少一個小寫字母和一個大寫字母。

ps:有一點要注意,上面展示的表達式解析時\d這些特殊符號在我們的代碼中多了一個\,這是因為\本身是轉義符號,為了保證表達式能正常匹配,我們要給\進行一次轉義,所以就變成了\\。基本上所有的符號字符都需要轉義。

語法/字符說明表

值表達

. ? ? ?匹配除換行符外的任意字符

\w ? 匹配字母或者數(shù)字的字符

\W ? 匹配任意不是字母或數(shù)字的字符

\s ? ?匹配任意的空白符(空格、制表符、換行符)

\S ? ?匹配任意不是空白符的字符

\d ? ?匹配任意數(shù)字

\D ? ?匹配任意非數(shù)字的字符

\b ? ?匹配單詞的結尾或者開頭的字符

\B ? ?匹配任意不是單詞結尾或開頭的字符

[^x] ?匹配任意非x的字符。如[^[a-z]]匹配非小寫字母的任意字符

^ ? ? ?匹配字符串的開頭

$ ? ? ?匹配字符串的結尾

修飾表達

* ? ? 匹配重復任意次數(shù)

+ ? ?匹配重復一次以上的次數(shù)

? ? ? ?匹配一次或零次

{n} ? ?匹配重復n次

{n,} ? 匹配重復n次或n次以上

{n,m} 匹配重復最少n次最多m次

除了上面列出的字符外,還有包括表示位置指定等較難運用的其他正則表達式,但上面的字符已經(jīng)足夠我們正常使用了。想了解更多知識可以度娘Google。

代碼實操

上面我們只是簡單的講解了正則表達式中各個字符代表的意義,那么在iOS開發(fā)中應該怎么使用。對于有意使用正則規(guī)則來匹配的開發(fā)者,我的建議是封裝成為類別方法,一次封裝,多次調用。下面用我自己封裝的代碼進行說明。這些方法通過擴展UITextField方法來實現(xiàn):

@interface UITextField (LXDValidate)

/*! 判斷文本框是否為空(非正則表達式)*/

- (BOOL)isEmpty;

/*! 判斷郵箱是否正確*/

- (BOOL)validateEmail;

/*! 判斷驗證碼是否正確*/

- (BOOL)validateAuthen;

/*! 判斷密碼格式是否正確*/

- (BOOL)validatePassword;

/*! 判斷手機號碼是否正確*/

- (BOOL)validatePhoneNumber;

/*! 自己寫正則傳入進行判斷*/

- (BOOL)validateWithRegExp: (NSString *)regExp;

@end

方法實現(xiàn)文件:

#import "UITextField+LXDValidate.h"

@implementation UITextField (LXDValidate)

- (BOOL)isEmpty

{

return self.text.length == 0;

}

- (BOOL)validateEmail

{

return [self validateWithRegExp: @"^[a-zA-Z0-9]{4,}@[a-z0-9A-Z]{2,}\\.[a-zA-Z]{2,}$"];

}

- (BOOL)validateAuthen

{

return [self validateWithRegExp: @"^\\d{5,6}$"];

}

- (BOOL)validatePassword

{

NSString * length = @"^\\w{6,18}$";? ? ? ? ?//長度

NSString * number = @"^\\w*\\d+\\w*$";? ? ? //數(shù)字

NSString * lower = @"^\\w*[a-z]+\\w*$";? ? ? //小寫字母

NSString * upper = @"^\\w*[A-Z]+\\w*$";? ? ?//大寫字母

return [self validateWithRegExp: length] && [self validateWithRegExp: number] && [self validateWithRegExp: lower] && [self validateWithRegExp: upper];

}

- (BOOL)validatePhoneNumber

{

NSString * reg = @"^1\\d{10}$";

return [self validateWithRegExp: reg];

}

- (BOOL)validateWithRegExp: (NSString *)regExp

{

NSPredicate * predicate = [NSPredicate predicateWithFormat: @"SELF MATCHES %@", regExp];

return [predicate evaluateWithObject: self.text];

}

@end

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,527評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,687評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,640評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,957評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,682評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,011評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,009評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,183評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,714評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,435評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,665評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,148評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,838評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,251評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,588評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,379評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,627評論 2 380

推薦閱讀更多精彩內容