正则表达式是一种强大的工具,虽然看起来非常复杂,实际上遵循着非常严格和简单的规则。通过并不太长时间的学习,你就能了解如何写出适合自己使用的正则表达式。
这里,是我在学习正则表达式的时候,记录的一些学习心得。入门我是通过网上非常有名的这篇<30分钟正则表达式入门>来完成学习的。在记录完笔记后,在各种应用场合,不断的尝试写出适合的正则表达式,我非常容易的掌握到正则表达式的规则。希望你也能抽出半天时间(30分钟当然是不可能的),就可以完成正则表达式这一强大工具的学习。
原文是针对C#正则技巧的内容,和OC应稍有区别,但入门知识基本相同。OC和大多数其他语言,不支持C#中的平衡组等复杂用法
Mac上正则表达式推荐工具可以使用:Reggy来做验证和测试,免费开源好用。
基本概念
hi
– 匹配所有等于hi的字符(不区分大小写)
bhib
– b为元字符(metacharacter),代表一个单词的开头和结尾(分界处-一般是空格、标点、换行).
– 精确匹配hi
单词
bhib.*bLucyb
– 查找hi和Lucy中间的内容
– .
代表除换行符以外任意字符
– *
代表数量,任意次数
– .*
代表任意数量不包含换行符的字符
0dd-dddddddd
或者 0d{2}-d{8}
– 以0开头,两位数字后有-连字号,后面跟8位数字
– d
是匹配数字,-
不是元字符,只是普通字符
– {2}
由大括号包含的数字,意思是前面的元字符必须匹配几次
– {2,4}
是指匹配不少于2次,不多于4次
其他元字符:
s
匹配任意空白符,包括空格,制表[tab],换行、中文全角空格w
匹配字符或下划线或汉字+
+号也是匹配数量,但不同与*
,+
是必须重复匹配1次以上(*
可以匹配0次),?
是重复0次或一次
元字符 | 说明 |
---|---|
* | 重复零次或多次 |
+ | 重复一次或多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复不少于n次,不多于m次 |
^
和$
匹配查找字符串的开头和结尾,如果是增加了处理多行的选项,^
和$
意思是匹配一行的开始和结束是转义,会将后面的特殊元字符,转为普通字符(*、+、^、$、.等)
字符类
- 由
[
和]
包含起来的内容,即为需要匹配的内容,注意[``]
里的.?!
不需要加转义
- []内的-,代表从字符集起始到结束,例如
[0-9]
与d
意思一样,[a-z0-9A-Z]则代表所有英文字母和数字集合 (?0d{2}[)-]?d{8}
:(
是转义(,(?
代表首部出现(一次或零次d{2}
匹配0出现之后有2位数字- 后面的
[)-]
是指后面可以有)和-,[)-]?
代表)和-可以出现一次或零次 d{8}
为最后8位数字
分支条件
- 有几种规则,满足任意一种即为匹配
|
隔开的规则,即为分支规则0d{2}-d{8}|0d{3}-d{7}
:两种规则0d{2}-d{8}
或0d{3}-d{7}
满足任意一条即可(3位数字-8位数字或4位数字-7位数字)- 分支要注意各条件的顺序,匹配时从左至右匹配,如果满足某个分技,则不再管另一分支
d{5}-d{4}|d{5}
和d{5}|d{5}-d{4}
两个正则不一致- 前者是匹配美国邮编的标准(前5后4共9位数字,或者是5位数字)
- 后面只匹配5位的数字
分组
- 使用
(
和)
包围的条件,是为一组 - 可以对组(或称子表达式)使用后缀元字符条件,来限定这一分组匹配重复次数等
反义
- 查找非规定范围以外的字符
- 基本上小写是正常,大写是反义
- 反义排除的只是字母列表,无关顺序,即[^abc],会排队a,b,c三个字母,而不是排队abc顺序的三个字母。
元字符 | 说明 |
---|---|
W | 任意非字母、数字、下划线、汉字的字符 |
S | 任意非空白符的字符 |
D | 任意非数字的字符 |
B | 任意非开头和结束的位置 |
[^x ] |
任意非x 的字符 |
[^abcd ] |
任意非abcd 的字符 |
后向引用
- 使用小括号
()
包围起来的分组,会自动拥有一个从左自右的从1开始的编号 - 正则会先把匹配分组的结果捕获出来,以相应编号来组织,可以用
编号
的形式来对这相对应的结果进行进一步处理
b(w+)bs+1b
匹配重复出现的单词(叠词)
b(w+)b的结果会被捕获到编号为1的分组中
s一个空格
1 引用编号1分组的结果
即寻找一个单词空格后,再重复一次的单词,例Go Go
- 在括号开始的地方,用
?<名字>
或者?'名字'
可以自定义分组名. - 自定义的分组名,使用
k<名字>
来调用 (?:)
如果在括号开始用?:
的话,即表示这一括号即不保存捕获的结果,也不给这一括号分配组号
零宽断言
- 零宽断言是指查找某些内容前后的文本,但不包含这些内容本身。
b
,^
,$
这几个关键字,其实也是一种零宽断言- 零宽断言主要用来查找
(?=关键词表达式)
: (零宽度正预测先行断言)断言关键词
出现的位置后面能匹配表达式
。
bw+(?=ingb)
匹配以ing结尾的单词前半部分 : being 会匹配出be(?<=关键词表达式)
(零宽度正回顾后发断言):断言关键词
出现的位置前面能匹配表达式
(?<=bre)w+b
匹配以re开头的单词的后半部分: replay 会匹配出play(?!关键词表达式)
(零宽度负预测先行断言):断言关键词
出现的位置后面不能匹配表达式
bw*q[^u]w*b
:匹配q后面不包含u的单词,但这一正则无法筛除最后一位是q的情况,则”Iraq fighting”也会被匹配。因为[^u]占用了一个字符位。
bw*q(?!u)w*b
:使用零宽负预测先行断言,即可解决这种问题,它只匹配位置,并不消费(使用)任何位置。(?<!关键词表达式)
(零宽度负回顾后发断言):断言关键词
出现的位置前面不能匹配表达式
贪婪与懒惰(最大匹配和最小匹配)
- 默认是贪婪匹配:即在匹配条件的情况下,尽可能多的匹配字符。
- 在条件后加上
?
即可显式声明为懒惰匹配,即尽可能少的匹配字符
aabab 字串中,按
a.*b
,默认会匹配整个字符串
a.*?b
:则只匹配aab和ab
处理选项
- 大小写
- 多行模式:使
^
和$
匹配行首和行尾,而不仅仅是整个字符串的开头和结尾。 - 单行模式:更改
.
的含义,使.
代表所有字符(包含换行符) - 忽略空白:忽略表达式中的非转义空白,并启用
#
代表注释 - 显示捕获:仅显示捕获被声明的组,而不是给所有括号内的组默认命名(1~n)
平衡(对称)/递归匹配
- 需要匹配成对出现的内容
(?'标签名'条件)
满足条件,则把标签名入栈(?'-标签名'条件)
若满足条件,标签名出栈,如果栈为空,匹配失败(?(标签名)yes|no)
如果标签名的栈中有内容,则匹配yes规则,否则匹配no规则(?!)
总是失败的匹配,用来在平衡递归匹配中,中断匹配条件
注释
(?#注释)
:注释最好启用处理选项中的”忽略模式里的空白符“设置(C#)
不错的文章,内容惜墨如金.禁止此消息:[email protected]