java中的正则表达式(一)
最近在学习springMVC的源码并尝试从零开发一下web框架。在学习用遇到了一个拦路虎————正则表达式。在我平时的开发工作中对于正则表达式的使用并不是很频繁,可以说是几乎不用,即使用到了都是通过上网百度查询,久而久之正则表达式成了我的短板(虽然这块短板还没有影响我的工作)。在看了springMVC的框架后发现,其实正则表达式在封装框架中起着至关重要的作用,因此熟练的掌握正则表达式可以帮助我们学习底层的代码逻辑。
正则表达式:是一串字符,它描述了一种文本模式。这句话取自java编程的逻辑。正则表达式中的字符有两类,一类是普通字符用来匹配其本身,一类是元字符,这类字符有特殊的含义。这里需要注意一点,正则表达式有它自己的语法,许多的编程语言都支持正则表达式但是可能不同的语言对于正则表达式的语法解析是不同的,这里我介绍的是java中的正则表达式。
1.单个字符
绝大多数单个字符表示的就是其本身例如:‘A’,'B','C'。但是有一些字符是需要多个字符表示的,比如‘\n’换行 '\t'tab键。以八进制表示的字符要以‘\0’后面跟1~3位数字,以十六进制表示的字符要以‘\x’开头后面跟两个字符,以Unicode编号表示的字符要以‘\u’开头后面跟4个字符。在正则表达式中还有一些元字符:?、*、. 需要表示这些字符本身需要使用‘\’来转义例如:‘\?’,如果需要表示反斜杠本身需要'\\'即可。
2.字符组
在单个字符和任意字符中有一个字符组的概念表示匹配指定字符中的一个字符,在正则表达式中使用[]表示。例如:[sbcds]表示匹配s、b、c、d、s中的任意一个字符。为了方便的表示多个连接的字符,可以使用连字符‘-’来表示。[0-9]表示匹配0~9的任意一个字符;[a-z]表示匹配a~z的任意一个字符,如果需要匹配连接符‘-’可以把连接符写在[-a-z]写在最前面,也可以使用转义字符进行转义。在‘[’后面紧跟一个‘^’表示排除匹配,如果[^abcd]表示匹配除了abcd的任意字符,这里^在开头才表示元字符如果不在开头表示的就是普通的^。在字符组中除了[]\-^外,其他的元字符不具有任何特殊含义只表示其本身。有一些以\开头的字符,表示一些预定义的字符组,比如:\d表示匹配一个数字字符等同于[0-9]、\w表示匹配一个单词字符等同于[0-9a-zA-Z_]、\s表示匹配一个空白字符,它们都有对应的排除型字符组,只需要把\后面的字母修改成大写即可。
3.量词
量词的作用是指定前面元字符出现的次数,我介绍的量词有三个,分别是“+、*、?”。“+”表示匹配前面的原字符一次或多次、"*"表示匹配前面的字符零次或多次、“?”表示匹配前面的字符一次或零次。比起+、?、*使用更频繁的是{m,n},叫做通用量词表示前面的一个字符出现的次数最少m次,最多n次。如果n没有限制,n可以省略。关于量词有一个比较重要的是量词默认都是贪婪的,比如有这样的一个正则表达式:"<a>.*</a>",如果用这个表达式器匹配<a>e</a><a>b</a>,默认只会匹配一次而不是去分别匹配,遇到这种情况如果希望正则表达式去分配匹配可以在量词的后面加上一个‘?’也就是<a>.*?</a>。
4.分组
正则表达式可以用()表示分组,例如:“a(bcd)ef”,其中bcd就是一个分组。在正则表达式中每一个分组都有一个序号,默认从1开始从左向右递增,其中a(bcd)ef这表达式的第一个分组就是bcd。分组后可以使用量词修饰,比如“a(bcd)?ef”表示可以匹配abcdef也可以匹配aef。在使用分组()和元字符“|”结合可以实现和[]类似的功能表示匹配其中的一个字符例如:(aa|bb|cc)。在正则表达式中可以通过\加分组序号来表示之前匹配的分组,这就叫做回溯引用,例如:<(\w+)>aa</\1>其中\1表示的是匹配之前的分组<(\w+)>。使用数字序号分组有时可能会让用户混淆所以这时我们可以使用命名分组,对于声明命名分组的语法是:(?<name>X),引用分组的语法是:\k<name>,例如:<:(?<test>\w+)></\k<test>>。
5.边界匹配
在正则表达式中我们除了可以指定字符的匹配规则也可以指定字符的边界的匹配规则。我只介绍几种常用的边界匹配符号。1.边界^:表示匹配整个字符串的开始,例如^abc表示匹配以abc开头的字符串。注意如果在多行匹配模式下^ 也匹配 ’\n’ 或 ’\r’ 之后的位置。2.边界$:表示匹配整个字符串的末尾,如果设置的多行匹配模式$也匹配 ’\n’ 或 ’\r’ 之前的位置。3.\z表示匹配字符串结束的边界,包括换行符。4.\b表示匹配单词的边界,这个边界的要求是要求匹配的边界一边是单词而另一边不是单词才能匹配。
6.环视边界匹配
环视边界匹配表示的也是字符串的边界匹配,分别有对字符串的左边边界匹配和对右边边界匹配,我主要介绍四种环视边界匹配。1.肯定顺序环视,表示指定字符串边界的右边字符串的匹配模式,语法为:(?=...),例如:abc(?=23)表示可以匹配abc23但是不能匹配abc2。2.否定顺序环视,表示指定字符串边界的右边字符串不能匹配的模式,语法为:(!=...),例如:abc(!=23)表示除字符c后面不匹配有23的字符串。3.肯定逆序环视,表示指定字符串边界的左边字符串的匹配模式,语法为:(?<=...),例如:(?<=\d)abc表示字符串abc的左边必须是[0-9]的数字。4.否定逆序环视,表示指定字符串边界的左边字符串不能匹配的模式,语法为:(?<!...),例如:(?<!\d)abc表示字符串abc的左边不能是[0-9]的数字。