前言
开发中经常会用到正则表达式来匹配或者过滤目标字符串,从而提高自己的开发效率。本文主要通过介绍正则表达式,让你对正则表达式有一个基本的了解,从而可以应用在自己的开发过程中(主要是iOS 开发中,文中会有demo讲解),再次更深层次的学习不做讲解,文中有学习链接,有兴趣的可以进行更深层次的研究。
简介
正则表达式,又称正规表示式、正规表示法、正规表达式、规则表达式、常规表示法(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些匹配某个模式的文本。
许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功正则表达式则表达式引擎。正则表达式这个概念最初是由Unix中的工具软件(例如sed和gr正则表达式开的。正则表达式通常缩写成“regex”,单数有regexp、regex,复数有regexps、regexes、regexen。
-----维基百科
上面一大段书面式刻板的简介不知道大家有没有耐心看完,看到那么多专业且刻板的术语,读完还是不了解正则表达式到底是什么。其实上面的文字总结为一句话:正则表达式就是用于记录文本规则的代码。
举例说明:在使用windows过程中,我们经常使用 ? 和 * 通配符来查找硬盘上的文件。? 通配符匹配文件名中的单个字符,而 * 通配符匹配零个或多个字符。
使用 data?.zip 这样的模式将查找下列文件:>datas.zip
data1.zip
data2.zip
data3.zip
使用 * 字符代替 ? 字符扩大了找到的文件的数量。data*.dat 匹配下列所有文件:
datas.zip
dataSource.zip
dataArray.zip
dataDic.zip
这种搜索方式在使用电脑的日常生活中很有用,但是对于大多数的场景来说,它还是有限的。通过通配符的工作原理,引入正则表达式的概念。正则表达式和通配符类似,同样用于文本匹配,只不过跟通配符比较起来,正则表达式功能更加强大并且更加灵活,更加精确的描述你的需求。
常用功能
不管是文档编辑软件或者是IDE中都提供了搜索和替换功能,这些功能基本可以满足我们的一些基本操作,但是对于无法使用软件的情况下,我们想要从茫茫的数据中查找到与满足自己需求的数据,就又写捉襟见肘。通过正则表达式可以满足你的这些需求:
- 数据校验
正如上面所总结的:正则表达式就是用于记录文本规则的代码。我们写一段规则,通过特定的语法来查看目标字符串是否符合这个规则。例如:手机号校验、邮箱地址校验、密码(6-12位数字字母密码)校验等等 - 文本替换&文本提取首先通过正则表达式来识别某些特定文本,并对该特定文本执行提取、删除或替换等操作。
语法
正则表达式是由两种基本字符组成:普通字符(例如字符 a 到 z)以及特殊字符(称为"元字符" --- metacharacter)所组成的描述文本规则的代码。规则用来描述在搜索文本时要匹配的一个或多个字符串。正则表达式作为文本规则,将某个文本规则与所搜索的字符串进行匹配。
入门
学习正则表达式最好的方法就是从现有的例子开始,理解例子之后,在其基础之上修改实验。在接下来的讲解中,会结合简单的例子来加深对正则表达式的理解。
元字符
元字符就是指那些在正则表达式中具有特殊意义的专用字符,用来规定其前导字符(位于元字符前面的字符)在目标对象中的出现规则,一个元字符可以用来匹配一个或者多个字符。
总结:元字符就是正则表达式中用来描述一个文本规则的专用字符。
举例:精确查找“ab”在未使用正则表达式之前,查找ab,我们可能会得到以下结果
abc
cab
cabc
元字符:\b精确查找的ab字符的正则表达式为:\bab\b 。\b 代表文本的开头或者结尾,也就是文本的边界,上面的正则表达式表示的意思是 :以a开头,以b结尾的文本规则。并且\b 并不会匹配分隔字符(空格、标点符号、换行符)中的任何一个,只是单纯的匹配一个位置。
元字符:.可以理解为匹配除换行符以外的任意字符**
元字符:* 代表的不是字符(因为正则表达式*是用于描述文本规则的一段代码,代表规则,不代表字符),也不是位置,而是数量----它指定前边的内容可以连续重复使用任意次以使整个表达式得到匹配。
元字符:\d可以用于匹配一个数字(0-9),举例说明:0\d\d-\d\d\d\d\d\d\d\d 匹配这样的字符串:以0开头,然后是两个数字,然后是一个连字号“-”,最后是8个数字(用来匹配中国的座机号,当然,这个例子只能匹配区号为3位的情形)。当然表达同样的意思还有一个简单的写法:0\d{2}-\d{8} 这里\d后面的{2}和{8}的意思是前面\d必须连续重复匹配2次和8次。
综合例子: \bCrab\b.*\bMan\b:用于匹配以Crab开头,中间跟着任意个数任意字符,然后以Man结尾的字符串
元字符 | 说明 |
---|---|
. | 匹配除换行符以外的任意字符 |
\w | 匹配字母或数字或下划线或汉字 |
\s | 任意的空白符,包括空格,制表符(Tab),换行符,中文全角空格等 |
\d | 匹配数字(0-9) |
\b | 匹配单词的开始或结束 |
^ | 匹配字符串的开始 |
$ | 匹配字符串的结束 |
结合例子说明:
\ba\w\b匹配以字母a开头的单词——先是某个单词开始处(\b),然后是字母a,然后是任意数量的字母或数字(\w),最后是单词结束处(\b)。\d+** 匹配1个或更多连续的数字。这里的+是和*类似的元字符,不同的是*匹配重复任意次(可能是0次),而+则匹配重复1次或更多次。\b\w{6}\b 匹配刚好6个字符的单词。元字符 ^(和数字6在同一个键位上的符号)和 $ 都匹配一个位置,这和\b有点类似。^匹配你要用来查找的字符串的开头,$ 匹配结尾。这两个代码在验证输入的内容时非常有用,比如一个网站如果要求你填写的QQ号必须为5位到12位数字时,可以使用:^\d{5,12}$。这里的 {5,12} 和前面介绍过的{2}是类似的,只不过{2}匹配只能不多不少重复2次,{5,12} 则是重复的次数不能少于5次,不能多于12次,否则都不匹配。因为使用了 ^ 和 $,所以输入的整个字符串都要用来和 \d{5,12} 来匹配,也就是说整个输入必须是5到12个数字,因此如果输入的QQ号能匹配这个正则表达式的话,那就符合要求了。
限定符
正则表达式中提供了有一类用于限定字符数量的符号,称为 限定符。并且限定符分为两种 :
- 贪婪的:尝试尽可能多的匹配元素
- 惰性(非贪婪)的:尽可能的少的匹配元素
通过添加问号即 ?可以将贪婪限定符转为惰性限定符。
从前面的综合例子中,大概已经知道了限定字符数量的字符 例如 :* ,+,{2}...
贪婪限定符 | 惰性限定符 | 说明 |
---|---|---|
* | *? | 重复零次或更多次 |
+ | *+ | 重复一次或更多次 |
? | ?? | 重复零次或一次 |
{n} | {n}? | 重复n次 |
{n,} | {n,}? | 重复n次或更多次 |
{n,m} | {n,m}? | 重复n到m次 |
关于贪婪限定符与惰性限定符之间的区别以及完整介绍,戳这里进一步了解
参考文档:
《正则表达式30分钟入门教程》
《正则表达式必知必会》
正则表达式在iOS中的应用
1.NSString的方法
- (NSRange)rangeOfString:(NSString *)aString options:(NSStringCompareOptions)mask{
NSString *searchText = @"rangeOfString";
NSRange range = [searchText rangeOfString:@"^[0-9]+$" options:NSRegularExpressionSearch];
if (range.location != NSNotFound) {
NSLog(@"range :%@", [searchText substringWithRange:range]);
}
2.NSPredicate
Cocoa框架中的NSPredicate用于查询,原理和用法都类似于SQL中的where,作用相当于数据库的过滤取。 我们可以编写简单的谓词语句,就可以从数组中过滤出我们想要的数据。 代码示例:
+ (BOOL)validateEmail:(NSString *)email{
NSString *emailRegex = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";
NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegex];
return [emailTest evaluateWithObject:email];
}
3.NSRegularExpression
NSRegularExpression这个类是苹果专门封装的一个用来处理正则表达式的类。
代码示例:
objectivecNSString *searchText = @"you want to match";
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^[0-9]+$" options:NSRegularExpressionCaseInsensitive error:&error];
NSTextCheckingResult *result = [regex firstMatchInString:searchText options:0 range:NSMakeRange(0, [searchText length])];
if (result) {
NSLog(@"%@", [searchText substringWithRange:result.range]);
}
未完待续....