iOS开发-正则表达式

转自:Sindri的小巢

原文链接:http://www.jianshu.com/p/00da4d87b777 

正则表达式是一种用来进行文本匹配的工具,其语法优美简洁。在开发中,查找、对比以及匹配字符串是家常便饭的业务,通过正则表达式我们将这些业务描述成某些需求规则,来让我们的代码更美观、实用。例如我们要验证用户输入的密码长度是否满足6~18位的长度,新手最常见的验证方式是判断输入的密码长度。

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

尽管这种判断方式没有任何问题,而上面的验证换做正则表达式的匹配字符就显得短小精悍

^.{6,18}$

还有,大部分的固定电话都是0区号-八位数字的格式,那么正则表达式的匹配如下

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

再比如,对于密码强度的认证。如今的密码应该包括一个或以上的大写字母以及小写字母,对此正则表达式的匹配是

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

表达式字符解析

如果是新手开发者,那么很有可能不理解上面的正则表达式。那么我们先看第一个匹配条件,匹配6-18位的密码长度。根据题目的要求,就能够轻易的判断出{6,18}表示6-18位。其中,{n}匹配字符重复n次;{n,}匹配重复n次或更多次;{n,m}匹配重复n到m之间次数。

那么读者对^、.和$三个符号可能不明所以。^和$属于特殊符号,前者表示匹配字符串的开头,后者表示匹配字符串的结尾。由于我们有时需要在一段很长的字符串中匹配某些小片段字符串时(比如在图文混编中匹配长字符串中留空的表情符号),适当使用这两个符号可以减少匹配次数,提高执行效率。

那么结合这几个字符代表含义,可以得出.符号表示任一字符(除换行符之外)。那么还可以得出{6,18}这个特殊符号表示的是前一个符号代表的位数。结合起来说^.{6,18}$匹配一段6至18位长度的字符串,所以可以用来验证密码长度。

当然了,.字符的匹配率太高,更多时候我们需要匹配的是具体到数字或者字母,甚至准确的数字和字母。那么除了.字符以外,还有\d用来表示任意的单个数字,\w表示任意一个字母或数字或者直接使用0-9的任意数字表示具体数字。而特殊符号?表示前一个字符为0或者1个。

所以上面的^0\\d{2}\-?\\d{8}$匹配了以数字0开头,接着两个数字,后面跟着-号跟八个数字,然后结尾的字符串,不管是010-88888888,还是02098989898都能进行正确匹配。

最后的一个表达式可能是最复杂的表达式,根据上面对部分符号的解析。我们可以把

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

拆分成

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

这两个单独的表达式,而中间的|不难猜到就是逻辑的或。我们将对前一个进行拆分,来一步步识别这个表达式的匹配规则。这里教大家我拆分表达式的方法:我把表达式的字符分为两类:值表达和修饰表达。所谓值表达就是说这个符号表示了某个值,就像\d表示数字,.表示任意非换行符字符。修饰表达用来修饰值达成某种条件,比如{2}表示前面一个值重复两次,*表示前一个值重复0次或者更多次。根据这种方法,那么^.*[A-Z]+.*[a-z]+.*$可以拆分成部分:^$、 .* 、 [A-Z]+ 、 [a-z]+。

^$就不再多说。

.*这里要介绍的就是*表示前一个值符号重复任意次数。

[A-Z]+中-表示从左边的值到右边的值之间所有值形成的闭集合;[]方括号表示的值必须是括号中间集合的子集,要注意的是括号里面可以有多个集合,比如[A-Z0-9a-z]表示匹配任意一个大小写字母或数字;+同*有点像,但是+表示的是至少一个的重复值。

结合上面的解析,那么^.*[A-Z]+.*[a-z]+.*$表示以任意数量的字符开头,然后跟着一个大写字母,大写字母后面有任意数量的字符以及一个小写字母,然后又是任意数量的数字、字母或者字符。而^.*[a-z]+.*[A-Z]+.*$表示小写字母在大写字母前面任意数量的字符的位置,两个结合匹配可以确保字符串中包括至少一个小写字母和一个大写字母。

ps:有一点要注意,上面展示的表达式解析时\d这些特殊符号在我们的代码中多了一个\,这是因为\本身是转义符号,为了保证表达式能正常匹配,我们要给\进行一次转义,所以就变成了\\。基本上所有的符号字符都需要转义。

语法/字符说明表

值表达

.      匹配除换行符外的任意字符

\w   匹配字母或者数字的字符

\W   匹配任意不是字母或数字的字符

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

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

\d    匹配任意数字

\D    匹配任意非数字的字符

\b    匹配单词的结尾或者开头的字符

\B    匹配任意不是单词结尾或开头的字符

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

^      匹配字符串的开头

$      匹配字符串的结尾

修饰表达

*     匹配重复任意次数

+    匹配重复一次以上的次数

?      匹配一次或零次

{n}    匹配重复n次

{n,}   匹配重复n次或n次以上

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

除了上面列出的字符外,还有包括表示位置指定等较难运用的其他正则表达式,但上面的字符已经足够我们正常使用了。想了解更多知识可以度娘Google。

代码实操

上面我们只是简单的讲解了正则表达式中各个字符代表的意义,那么在iOS开发中应该怎么使用。对于有意使用正则规则来匹配的开发者,我的建议是封装成为类别方法,一次封装,多次调用。下面用我自己封装的代码进行说明。这些方法通过扩展UITextField方法来实现:

@interface UITextField (LXDValidate)

/*! 判断文本框是否为空(非正则表达式)*/

- (BOOL)isEmpty;

/*! 判断邮箱是否正确*/

- (BOOL)validateEmail;

/*! 判断验证码是否正确*/

- (BOOL)validateAuthen;

/*! 判断密码格式是否正确*/

- (BOOL)validatePassword;

/*! 判断手机号码是否正确*/

- (BOOL)validatePhoneNumber;

/*! 自己写正则传入进行判断*/

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

@end

方法实现文件:

#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*$";      //数字

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容