正则表达式
序言
好久没写过文章啦,距离自己上一次的记录已经过去了半年多了,也许是工作忙了,也许是自己懒惰了,也许是...最近的工作不怎么忙,心就想着要写点什么呢,由于同事的几句话,真的"机缘巧合"的写了这个知识,虽然这个知识点有点陈旧哈,但我相信对于那些对正则刚入门初学的开发者来说,你认真看过这篇文章之后,对于正则的认识、语法规则必会有一个大大提升的,若再附加自己的实践,相信你对于掌握好这个知识点是没有什么问题的哈,
含义
是由普通字符(字符 a 到 z)以及特殊字符("元字符")组成的文字模式(即字符串文本的复杂处理(查找、匹配、验证))
核心
正则表达式的语法规则
原则
尽可能罗列出所有出现的情况,然后再按照罗列的字符串写出符合要求的正则表达式,尽可能的精确匹配
建议
虽然现在常见的正则表达式我们都可以查到,但还是应该对正则语法有一些认识,不可生搬硬套别人的正则表达式
普通字符
包括没显式指定为元字符的所有可打印和不可打印字符(所有大写和小写字母、所有数字、所有标点符号和一些其他符号)
特殊字符
若匹配这些特殊字符,须先使用转义字符\
放在它们前面
几点说明
- 匹配包括 '\n' 在内的任何单字符 -
[.\n]
- 选择符
|
一般结合非捕获元字符?:
和分组()
搭配使用,因为它的优先级最低 - 分组
()
是对于复杂的文本分割成子表达式使用,一般结合反向引用\n
使用,这时编号是按照左括号往右的一次叠加的,即:编号从 1 开始,最多可存储 99 个捕获的子表达式,场景: 匹配重复出现的字符串 - 中括号表达式(字符簇)
[]
,表示所有字符的字符簇(集合),若在中括号表达式中包括连字符-
,则需要用反斜扛将它转义,但是若将连字符放在中括号列表的开始或结尾,则不需反斜扛转义
非打印字符
下图列出了非打印字符的转义序列
限定符
限定符用来指定正则的一个子表达式出现多少次能满足匹配,共6种
几点说明
- 限定符
*
、+
、?
都是贪婪的,它们会尽可能多的匹配所搜索的字符串,只有在它们的后面加上一个?
就可以实现非贪婪或最小匹配 - 即:
?
放在任何一个其他限定符 (*
,+
,?
,{n}
,{n,}
,{n,m}
) 后面时,匹配模式是非贪婪的,非贪婪模式会尽可能少的匹配所搜索的字符串(比如:对于字符串 "chongzoneeeee",'e+?' 将匹配单个 "e",而 'e+' 将匹配所有 'e'),场景:检测字符串是否包含某个字符等
定位符
定位符使您能够将正则固定到行首或行尾
注意点
不能将限定符与定位符一起使用,因为在紧靠换行或字边界的前面或后面不能有一个以上位置
预搜索(零宽断言assert)
零宽断言是对位置的匹配,共4种(下图列出了常见的2种)
几点说明
- (?:pattern) - 分组虽然使匹配更加清晰,但同时会产生一个副作用,使相关的匹配被缓存(存储到一个临时缓冲区中),此时使用
?:
放在分组选项前可消除这种副作用,不捕获匹配的文本,即:不给分组分配组号,则此时对于重复的字符串就不能使用反向引用 - (?=pattern) - 匹配以pattern结尾的前面的部分字符串,不包括pattern部分
- (?<=pattern) - 匹配以pattern开头的后面的部分字符串,不包括pattern部分
- (?!pattern) - 断言位置的后面不能匹配表达式pattern
- (?<!pattern) - 断言位置的前面不能匹配表达式pattern
即: (?=pattern)
和(?!pattern)
放在后面,(?<=pattern)
和(?<!pattern)
放在前面,场景: 取出需要的字符串
反向引用
反向引用用于重复搜索前面某个分组匹配的子表达式,当然也可以自己指定子表达式的组名
语法规则
(?<name>\w+)(或':(?'name'\w+))
,这样组名\w+的就定为name
,若是反向引用这个分组,则使用\k<name>
,即: \b(?<name>\w+)\b\s+\k<name>\b
其他元字符
不常用的其他元字符
- 模式修改符 -
(?i)
开 和(?-i)
关 - 包含区域不区分大小写 - 不建议使用 - 注释 -
(?#comment)
,对于不熟悉的匹配规则可以使用
运算符的优先级
下表从上到下列出了优先级最高到最低的排序
常用的正则表达式
写到这里的时候,自己呢本是不想写这个常用正则表达式部分的,但基于我看到的其他开发者写的或归纳整理的正则表达式,大部分都是COPY下来的,里面的有些正则表达式明显是有错误的...这样传阅下来估计会误导不少初学者呢,虽然对客户端开发者来说,正则使用的不是很频繁,在开发中用到的也就那么几种,现在的互联网这么发达,百度谷歌下不就知道啦,当然了还有另一个原因,由于正则的语法比较繁琐,时间一长不经常使用的话难免有些正则会被遗忘的,这样整理的话自己以后使用也是很方便的,好记性比不上烂笔头嘛,哈哈,废话就不多说了,有什么写的不对的地方请多多交流哈(ノへ ̄、)
1.用户名(首字母,长度6-16)
"^[a-zA-Z]\\w{5,15}$"
2.表单密码(长度6-16)
"^\\.{6,16}$"
3.验证码(长度6)
"^\\d{6}$"
4.固话号码(首数字0)
"^0\\d{2,3}-\\d{7,8}$"
5.手机号码(长度11)
"1|[34578]\\d{9}"
6.银行卡号(长度16-19)
@"^\\d{16,19}$"
7.身份证号(长度18,长度15已淘汰)
"^\\d{17}[\\dxX]$"
8.Email地址(.com、.cn等)
"^\\w+@\\w+(\\.[a-zA-Z]{2,3}){1,2}$"
9.仅含数字
"^\\d+$”
10.仅含字母
"^[a-zA-Z]+$"
11.仅含数字和字母
"^[0-9a-zA-Z]+$"
12.整数
"^\\-?\\d+$"
13.小数
"^\\d+\\.\\d*$"
14.浮点数
"^\\-?\\d+\\.?\\d*$"
15.正整数(最小1)
"^\\+?[1-9]\\d+$"
16.负整数(最大-1)
"^\\-[1-9]+$"
17.n位的小数
"^\\d+\\.\\d{n}$"
18.月份(长度1\2)
"^(0?[1-9]|1[0-2])$"
19.日数(最大31)
"^((0?[1-9])|((1|2)[0-9])|30|31)$"
20.含空白行
"\\s*"
21.首位空白符
"^\\s+|\\s+$"
22.含双字节
"[^\x00-\xff]"
23.包含中文(检测工具不支持)
"[\\u4e00-\\u9fa5]+"
24.搜索叠词
"\\b([a-z]+) \1\\b"
25.含n个字母的单词
"[[:alpha:]]{n}"
26.中国邮编(长度6)
"^[1-9]\\d{5}$"
27.QQ号码(最小5位,目前最大10位)
"^[1-9]\\d{5}$"
28.HTML标签
"<\\s*(\\S+)(\\s[^>]*)?>[\\s\\S]*<\\s*\\/\\1\\s*>"
29.网络URL(附带端口号匹配)
"http(s?):\\/\\/([^\\/:]+)(:\\d*)?([^ ]*)"
30.网页图片
"\\< *[img][^\\\\>]*[src] *= *[\\"\\']{0,1}([^\\"\\'\\ >]*)"
31.IP地址
"^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$"
iOS开发中的使用
在iOS开发中,Cocoa框架给我们提供了谓词NSPredicate
类,类似过滤器的作用,就相当于SQL
的where
条件,在iOS开发中,我们常用的做法将谓词和正则表达式配合使用,代码如下:
/**
* 匹配字符串
*
@param inputText 输入的文本
@param validRegular 正则表达式
@return YES 匹配成功 NO 匹配失败
*/
- (BOOL)verifysInputText:(NSString *)inputText validRegular:(NSString *)validRegular {
NSPredicate *predicte = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",validRegular];
return [predicte evaluateWithObject:inputText];
}
结束语
最后呢,推荐给大家一个在线的正则表达式检测工具Regex101,当然在Mac端,你也可以下载一个客户端RegExRx,不过它不是免费的,需要30块大洋,但它的界面简洁,为了学习嘛,都懂的,当然你也可以下载个破解版...
(ps:在检测工具内,单斜杠\
不需要转为双斜杠\\
,因为只有在代码中,编译器是默认单斜杠为转义字符,需要你转为双斜杠,所以上面你 看到的代码全是双斜杠的\\
,还有就是基本常见的检测工具都是不支持检测中文输入的,因为不能识别 "\u" 字符)
对于这个知识点、文章有什么不太理解的地方,还请在下面留言,看到之后有时间会回复的... 午安。。。