首页 > 代码库 > iOS 玩转正则运算
iOS 玩转正则运算
元字符
<style>body { font-family: Helvetica, arial, sans-serif; font-size: 14px; line-height: 1.6; padding-top: 10px; padding-bottom: 10px; background-color: white; padding: 30px } body>*:first-child { margin-top: 0 !important } body>*:last-child { margin-bottom: 0 !important } a { color: #4183C4 } a.absent { color: #cc0000 } a.anchor { display: block; padding-left: 30px; margin-left: -30px; cursor: pointer; position: absolute; top: 0; left: 0; bottom: 0 } h1,h2,h3,h4,h5,h6 { margin: 20px 0 10px; padding: 0; font-weight: bold; cursor: text; position: relative } h1:hover a.anchor,h2:hover a.anchor,h3:hover a.anchor,h4:hover a.anchor,h5:hover a.anchor,h6:hover a.anchor { background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA09pVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoMTMuMCAyMDEyMDMwNS5tLjQxNSAyMDEyLzAzLzA1OjIxOjAwOjAwKSAgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OUM2NjlDQjI4ODBGMTFFMTg1ODlEODNERDJBRjUwQTQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OUM2NjlDQjM4ODBGMTFFMTg1ODlEODNERDJBRjUwQTQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo5QzY2OUNCMDg4MEYxMUUxODU4OUQ4M0REMkFGNTBBNCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo5QzY2OUNCMTg4MEYxMUUxODU4OUQ4M0REMkFGNTBBNCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PsQhXeAAAABfSURBVHjaYvz//z8DJYCRUgMYQAbAMBQIAvEqkBQWXI6sHqwHiwG70TTBxGaiWwjCTGgOUgJiF1J8wMRAIUA34B4Q76HUBelAfJYSA0CuMIEaRP8wGIkGMA54bgQIMACAmkXJi0hKJQAAAABJRU5ErkJggg==") no-repeat 10px center; text-decoration: none } h1 tt,h1 code { font-size: inherit } h2 tt,h2 code { font-size: inherit } h3 tt,h3 code { font-size: inherit } h4 tt,h4 code { font-size: inherit } h5 tt,h5 code { font-size: inherit } h6 tt,h6 code { font-size: inherit } h1 { font-size: 28px; color: black } h2 { font-size: 24px; border-bottom: 1px solid #cccccc; color: black } h3 { font-size: 18px } h4 { font-size: 16px } h5 { font-size: 14px } h6 { color: #777777; font-size: 14px } p,blockquote,ul,ol,dl,li,table,pre { margin: 15px 0 } hr { background: transparent url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAECAYAAACtBE5DAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OENDRjNBN0E2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OENDRjNBN0I2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4Q0NGM0E3ODY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4Q0NGM0E3OTY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PqqezsUAAAAfSURBVHjaYmRABcYwBiM2QSA4y4hNEKYDQxAEAAIMAHNGAzhkPOlYAAAAAElFTkSuQmCC") repeat-x 0 0; border: 0 none; color: #cccccc; height: 4px; padding: 0 } body>h2:first-child { margin-top: 0; padding-top: 0 } body>h1:first-child { margin-top: 0; padding-top: 0 } body>h1:first-child+h2 { margin-top: 0; padding-top: 0 } body>h3:first-child,body>h4:first-child,body>h5:first-child,body>h6:first-child { margin-top: 0; padding-top: 0 } a:first-child h1,a:first-child h2,a:first-child h3,a:first-child h4,a:first-child h5,a:first-child h6 { margin-top: 0; padding-top: 0 } h1 p,h2 p,h3 p,h4 p,h5 p,h6 p { margin-top: 0 } li p.first { display: inline-block } li { margin: 0 } ul,ol { padding-left: 30px } ul :first-child,ol :first-child { margin-top: 0 } dl { padding: 0 } dl dt { font-size: 14px; font-weight: bold; font-style: italic; padding: 0; margin: 15px 0 5px } dl dt:first-child { padding: 0 } dl dt>:first-child { margin-top: 0 } dl dt>:last-child { margin-bottom: 0 } dl dd { margin: 0 0 15px; padding: 0 15px } dl dd>:first-child { margin-top: 0 } dl dd>:last-child { margin-bottom: 0 } blockquote { border-left: 4px solid #dddddd; padding: 0 15px; color: #777777 } blockquote>:first-child { margin-top: 0 } blockquote>:last-child { margin-bottom: 0 } table { padding: 0; border-collapse: collapse } table tr { border-top: 1px solid #cccccc; background-color: white; margin: 0; padding: 0 } table tr:nth-child(2n) { background-color: #f8f8f8 } table tr th { font-weight: bold; border: 1px solid #cccccc; margin: 0; padding: 6px 13px } table tr td { border: 1px solid #cccccc; margin: 0; padding: 6px 13px } table tr th :first-child,table tr td :first-child { margin-top: 0 } table tr th :last-child,table tr td :last-child { margin-bottom: 0 } img { max-width: 100% } span.frame { display: block; overflow: hidden } span.frame>span { border: 1px solid #dddddd; display: block; float: left; overflow: hidden; margin: 13px 0 0; padding: 7px; width: auto } span.frame span img { display: block; float: left } span.frame span span { clear: both; color: #333333; display: block; padding: 5px 0 0 } span.align-center { display: block; overflow: hidden; clear: both } span.align-center>span { display: block; overflow: hidden; margin: 13px auto 0; text-align: center } span.align-center span img { margin: 0 auto; text-align: center } span.align-right { display: block; overflow: hidden; clear: both } span.align-right>span { display: block; overflow: hidden; margin: 13px 0 0; text-align: right } span.align-right span img { margin: 0; text-align: right } span.float-left { display: block; margin-right: 13px; overflow: hidden; float: left } span.float-left span { margin: 13px 0 0 } span.float-right { display: block; margin-left: 13px; overflow: hidden; float: right } span.float-right>span { display: block; overflow: hidden; margin: 13px auto 0; text-align: right } code,tt { margin: 0 2px; padding: 0 5px; white-space: nowrap; border: 1px solid #eaeaea; background-color: #f8f8f8 } pre code { margin: 0; padding: 0; white-space: pre; border: none; background: transparent } .highlight pre { background-color: #f8f8f8; border: 1px solid #cccccc; font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px } pre { background-color: #f8f8f8; border: 1px solid #cccccc; font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px } pre code,pre tt { background-color: transparent; border: none } sup { font-size: 0.83em; vertical-align: super; line-height: 0 } kbd { display: inline-block; padding: 3px 5px; font-size: 11px; line-height: 10px; color: #555; vertical-align: middle; background-color: #fcfcfc; border: solid 1px #ccc; border-bottom-color: #bbb } * { }</style>正则表达式记录表
元字符
1、 \b : 单词的开始或结束
2、 .* : 任意数量的不包含换行的字符
. : 匹配除换行符以外的任意字符
3、 \d : 是新的元字符,匹配一位数字
\d{n} : 必须连续重复匹配n次
4、 \s : 匹配任意的空白符(空格,制表格,换行符,中文全角空格等)
5、 \w : 匹配字母或者数字或者下划线或者汉字等
6、 ^ : 匹配字符串的开始
¥ : 匹配字符串的结束
注意:
* 字符转义
如果你想查找元字符本身,比如.和* ,这时候你就应该使用\.和\*
重复
代码 | 说明 |
---|---|
* | 重复零次或更多次 |
+ | 重复一次或更多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
注意:
*字符类
如果想匹配没有预定义的元字符集合,比如a,e,o。这时候你就要[aeo]就匹配任何一个英文元音的字母。[.?!]匹配任意一个标点符号
分枝条件
-
满足任意一种规则都应该当成匹配,用 | 把不同的规则分割开来
0\d{2}-\d{8}|0\d{3}-\d{7} 这个表达式能匹配两种以连字号分隔的电话号码:一种是三位区号,8位本地号(如010-12345678),一种是4位区号,7位本地号(0376-2233445) \(0\d{2}\)[- ]?\d{8}|0\d{2}[- ]?\d{8}这个表达式匹配3位区号的电话号码,其中区号可以用小括号括起来,也可以不用,区号与本地号间可以用连字号或空格间隔,也可以没有间隔
-
使用分枝条件时,要注意个分枝的顺序
\d{5}-\d{4}|\d{5} 换成 \d{5}|\d{5}-\d{4},那么就只会匹配5位的邮编。原因是匹配分枝条件时,将会从左到右地测试每个条件,如果满足了某个分枝的话,就不会去再管其它的条件了
-
重复多个字符,使用分组
(\d{1,3}\.){3}\d{1,3}是一个简单的IP地址匹配表达式 (\d{1,3}\.){3}匹配三位数字加上一个英文句号(这个整体也就是这个分组)重复3次,最后再加上一个一到三位的数字(\d{1,3}) 不幸的是,它也将匹配256.300.888.999这种不可能存在的IP地址 ((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)。解析正确IP:01-09,0-255 1. 2[0-4]\d :(200-249) 2. 25[0-5] :(250-255) 3. [01]?\d\d? : (01-09,0-199)
反义
代码 | 语法 |
---|---|
\W | 匹配任意不是字母,数字,下划线,汉字的字符 |
\S | 匹配任意不是空白符的字符 |
\D | 匹配任意非数字的字符 |
\B | 匹配不是单词开头或结束的位置 |
[^x] | 匹配除了x以外的任意字符 |
[^aeiou] | 匹配除了aeiou这几个字母以外的任意字符 |
例如:
\S+匹配不包含空白符的字符串。
<a[^>]+>匹配用尖括号括起来的以a开头的字符串
后向引用
常用分组语法
分类 | 代码/语法 | 说明 |
---|---|---|
捕获 | (exp) | 匹配exp,并捕获文本到自动命名的组里 |
(?exp | 匹配exp,并捕获文本到名称为name的组里,也可以写成(?‘name‘exp) | |
(?:exp) | 匹配exp,不捕获匹配的文本,也不给此分组分配组号 | |
零宽断言 | (?=exp) | 匹配exp前面的位置 |
(?<=exp) | 匹配exp后面的位置 | |
(?!exp) | 匹配后面跟的不是exp的位置 | |
(?<!exp) | 匹配前面不是exp的位置 | |
注释 | (?#comment) | 这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读 |
注意:
分组0对应整个正则表达式
实际上组号分配过程是要从左向右扫描两遍的:第一遍只给未命名组分配,第二遍只给命名组分配--因此所有命名组的组号都大于未命名的组号
你可以使用(?:exp)这样的语法来剥夺一个分组对组号分配的参与权
例如:
\b(\w+)\b\s+\1\b可以用来匹配重复的单词:html html
零宽断言
<?!w+> ?<!w+
\b\w*q[^u]\w*\b匹配包含后面不是字母u的字母q的单词。
你会发现,如果q出现在单词的结尾的话,像Iraq,Benq,这个表达式就会出错。这是因为[^u]总要匹配一个字符,所以如果q是单词的最后一个字符的话,后面的[^u]将会匹配q后面的单词分隔符(可能是空格,或者是句号或其它的什么),后面的\w*\b将会匹配下一个单词,于是\b\w*q[^u]\w*\b就能匹配整个Iraq fighting
负向零宽断言能解决这样的问题,因为它只匹配一个位置,并不消费任何字符。现在,我们可以这样来解决这个问题:\b\w*q(?!u)\w*\b
例如
\d{3}(?!\d)匹配三位数字,而且这三位数字的后面不能是数字;\b((?!abc)\w)+\b匹配不包含连续字符串abc的单词。
(?<![a-z])\d{7}匹配前面不是小写字母的七位数字。
(?<=<(\w+)>).*(?=<\/\1>)匹配不包含属性的简单HTML标签内里的内容:被尖括号括起来的单词(比如可能是<b>),然后是.*(任意的字符串),最后是一个后缀(?=<\/\1>)。注意后缀里的\/,它用到了前面提过的字符转义;\1则是一个反向引用,引用的正是捕获的第一组,前面的(\w+)匹配的内容,这样如果前缀实际上是<b>的话,后缀就是</b>了。整个表达式匹配的是<b>和</b>之间的内容(再次提醒,不包括前缀和后缀本身)
注释
代码 | 语法 |
---|---|
(?<= | # 断言要匹配的文本的前缀 |
<(\w+)> | # 查找尖括号括起来的字母或数字(即HTML/XML标签) |
( | # 前缀结束 |
.* | # 匹配任意文本 |
(?= | # 断言要匹配的文本的后缀 |
<\ / \1> | # 查找尖括号括起来的内容:前面是一个"/",后面是先前捕获的标签 |
) | # 后缀结束 |
例如:
2[0-4]\d(?#200-249)|25[0-5](?#250-255)|[01]?\d\d?(?#0-199)。
贪婪和懒惰
-
a.*b,它将会匹配最长的以a开始,以b结束的字符串。如果用它来搜索aabab的话,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符。它会匹配整个字符串aabab。这被称为贪婪匹配
-
a.*?b,它将会匹配最长的以a开始,以b结束的字符串。如果用它来搜索aabab的话,匹配任意数量的重复,(但是在能使整个匹配成功的前提下)使用最少的重复,会匹配aab和ab。这被称为懒惰匹配
注意:
为什么第一个匹配是aab(第一到第三个字符)而不是ab(第二到第三个字符)? 简单地说,因为正则表达式有另一条规则,比懒惰/贪婪规则的优先级更高: 最先开始的匹配拥有最高的优先权
-
懒惰限定符
代码 说明 *? 重复任意次,但尽可能少重复 +? 重复1次或更多次,但尽可能少重复 ?? 重复0次或1次,但尽可能少重复 {n,m}? 重复n到m次,但尽可能少重复 {n,}? 重复n次以上,但尽可能少重复
处理选项
注意:
Regex regex = new Regex(@"\ba\w{6}\b", RegexOptions.IgnoreCase);
常用的处理选项
名称 | 说明 |
---|---|
IgnoreCase | 匹配时不区分大小写 |
Multiline | 更改^和$的含义,使它们分别在任意一行的行首和行尾匹配,而不仅仅在整个字符串的开头和结尾匹配。(在此模式下,$的精确含意是:匹配\n之前的位置以及字符串结束前的位置.) |
Singleline | 更改.的含义,使它与每一个字符匹配(包括换行符\n) |
IgnorePatternWhitespace | 忽略表达式中的非转义空白并启用由#标记的注释。 |
ExplicitCapture | 仅捕获已被显式命名的组。 |
常用事例
说明 | 正则表达式 |
---|---|
网址(url) | [a-zA-z]+://[^\s]* |
IP地址 | ((2[0-4]\d |
电子邮件(email) | \w+([-+.]\w+)@\w+([-.]\w+).\w+([-.]\w+)* |
QQ号码 | [1-9]\d{4,} |
HTML标签 | <(.)(.)>.*<\/\1> |
密码(有数字/大写字母/小写字母/标点,8位以上) | (?=^.{8,}$)(?=.\d)(?=.\W+)(?=.[A-Z])(?=.[a-z])(?!.\n).$ |
日期 | (\d{4} |
汉字 | [\u4e00-\u9fa5] |
中文及全角标点符号 | [\u3000-\u301e\ufe10-\ufe19\ufe30-\ufe44\ufe50-\ufe6b\uff01-\uffee] |
注意:
ios 开发使用 RegexKit.framework 框架
使用规则:
昵称验证:(4-8)位汉字
+ (BOOL) validateNickname:(NSString *)nickname
{
NSString *nicknameRegex = @"^[\u4e00-\u9fa5]{4,8}$";
NSPredicate *passWordPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",nicknameRegex];
return [passWordPredicate evaluateWithObject:nickname];
}
密码验证:(6-20)位英文不分大小写和数字
+ (BOOL) validatePassword:(NSString *)passWord
{
NSString *passWordRegex = @"^[a-zA-Z0-9]{6,20}+$";
NSPredicate *passWordPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",passWordRegex];
return [passWordPredicate evaluateWithObject:passWord];
}
邮箱验证:
+ (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];
}
iOS 玩转正则运算
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。