一个正则表达式通常被称为一个模式(pattern),为用来描述或者匹配一系列符合某个句法规则的字符串。我们常用正则表达式来处理两种情况,一种是查找特定的信息(搜索),另外一种是查找并编辑特定的信息(替换)。
常用元字符及其作用:
一、匹配单个字符和一组字符
1. 匹配单个字符
(1). 元字符(英文句号)可以匹配任何一个单个的字符(单个的字符、数字、字母、.本身),相当于DOS的?字符和SQL的_字符。
(2)如果要匹配特殊字符(元字符)就要使用 \ 来对元字符进行转义,例如:\. 就匹配了 . 本身。
2. 匹配一组字符
(1)元字符[ 和 ] 用来定义一个字符集合,其含义是必须匹配该集合中的字符之一。定义一个字符集合的具体做法有两种:一种是把所有的字符都列出;二是利用元字符-以字符区间的方式给出。
其中,第一种例如:
文本:
na.xls
sa.xls
模式:[ns]a.xls
匹配结果:
na.xls
sa.xls
第二种例如:
文本:
na2.xls
sa1.xls
sa.xls
模式:[ns]a[0-9].xls
匹配结果:
na2.xls
sa1.xls
(2)字符集合还可以用元字符^求非,用^来表明你想对一个字符集进行取非匹配,即除了该集合中的字符,其它字符都可以匹配。
文本:
na2.xls
sa1.xls
sa.xls
模式:[ns]a[^0-9].xls
匹配结果:
sa.xls
注意:^的效果作用于给定字符集合的所有字符或字符区间,而不是仅限于紧跟在^字符后面的哪那一个字符或字符区间,且要置于集合[]中的开头位置。
二、元字符讲解
前面我们也已经接触到了元字符:. \ [ ] - ^ 。 正则表达式涉及的元字符见博客结尾。
(1)特殊字符的转义即对元字符的转义,由于正则表达式中对于规定的元字符会进行相应的处理,但是如果想使用元字符本身的符号就要使用转义字符 \ (反斜杆)作为该字符的前缀了。注意:\\ 匹配 \ 字符。
(2)空白元字符:
\r\n匹配一个“回车加换行”组合,\r\n\r\n进行的搜索将匹配两个连续的行尾标签,正是两条记录之间的空白行。
(3)数字元字符:
(4)字母数字元字符:
(5)空白字符元字符
注意:[\b]元字符是个特例,不在\s的覆盖范围内。
(6)POSIX字符类
该字符类是正则表达式的一种简写形式。
注意:这里使用的模式以[[开头,以]]结束(两对方括号)。这是使用POSIX必须的,外层的[和]字符用来定义一个字符集合,内层的[和]字符是POSIX字符类本身的组成部分。
三、重复匹配
(1)匹配一个或多个字符:
元字符+是匹配其前面一个字符的一个或多个字符(不匹配零个字符的情况),比如[0-9]匹配任意单个数字,[0-9]+将匹配一个或多个连续的数字。
注意:在给一个字符集合加上+后缀的时候,必须把+放在这个字符集合外面,比如说,[0-9]+是正确的,[0-9+]则不是,其表示是匹配0123456789+中的任意一个字符。
(2)匹配零个或多个字符
元字符*是匹配其前面一个字符的零个或多个字符。
例子:
文本:hello, .ben@forta.com is my email address,ben.forta@forta.c.com
模式: \w+[\w.]*@[\w.]+\.\w+
结果: ben@forta.com ben.forta@forta.c.com
分析:
开头的\w+负责匹配电子邮箱地址的第一个字符(一个字母数字字符,不包括.字符);[\w.]*覅则匹配电子邮箱地址的第一个字符之后,@字符之前的所有字符;[\w.]匹配@之后的电子邮箱的域名,包括可能出现的多层域名;\.\w+匹配地址的后缀名。
注意:我们没有对字符集合[\w.]中的.字符进行转义,尽管如此还是匹配出. ,一般来说,当在字符集合中使用 . 的时候,像 . 和+这样的元字符将被解释为普通字符,不需要被转义。
(3)匹配零个或多个字符
元字符?是匹配其前面一个字符的零个或一个字符。
(4)匹配的重复次数
重复次数要用{和}字符来给出,把要重复的字符写在它们前面,重复的次数写在他们之间。
例如:{3}意味着其前面前面一个字符必须在原始文本连续出现三次才算一个匹配;{2,4}意味着该字符最少重复2次,最多重复4次;{2,}意味着最少重复2次或更多次。
(5)防止过度匹配
来看一个例子:
文本:<B>abc</B> and <B> def</B>
模式:<[Bb]>.*</[Bb]>
结果:<B>abc</B> and <B> def</B>
原本我们想匹配两个<B></B>,可结果却是第一个<B>到最后的</B>。原因是*和+都是“贪婪型”元字符,它们在进行匹配时的行为模式时多多益善的而不是适可而止的,它们会尽量从一段文本的开头一直匹配到这段文本的末尾,而不是从开头匹配到第一个匹配时为止。解决的方法时转换成懒惰型,即在贪婪型元字符后加一个?元字符。
四、位置匹配
(1)单词边界
该边界时由限定符\b指定的单词边界,顾名思义,\b用来匹配一个单词的开始或结尾。
文本:the cat scattered
模式:\bcat\b
结果:cat
原始文本中,单词cat的前后都有要给空格,而这将与模式\bcat\b相匹配(空格是用来分隔单词的字符之一)。
(2)字符串边界
定义字符串边界的元字符有两个:一个是用来定义字符串开头的^(放在字符串的开头),另外一个是用来定义字符串结尾的$(放在字符串的结尾)。
五、子表达式
(1)子表达式是一个更大的表达式的一部分:把一个表达式划分成一系列子表达式的目的是为了把那些子表达式当作一个独立元素来使用,子表达式用元字符(和)括起来。例如:( ){2}是匹配 出现两次。
为了提高可读性,我喜欢把每一个子表达式都加上元字符(和)。
(2)限定符 |
| 字符是正则表达式语言的或操作符,19|20将匹配数字序列19或20,但注意:如果是19|20\d{2}匹配的是19或20\d{2},| 是将两边看成一个整体,如果要符合前面要求的,就得用元字符(和):(19|20)\d{2}。
(3)子表达式的嵌套:
文本:[12.158.46.200]
模式:(((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))\.){3}((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))
结果:12.158.46.200
分析:这是个IP地址的匹配,IP地址的匹配遵循:有四组数字,每组数字遵循:任何一个1位或2位数字;任何一个以1开头的3位数字;任何一个以2开头、第二位数字在0-4之间的三位数字;任何一个以25开头,第三位数字在0-5之间的三位数字。
六、回溯引用
先来看一个例子:
我们在匹配HTML标签的标题的时候,如果要匹配<H2><H2>和<H3><H3>这样成对匹配的话,我们如果用<hH[1-9]>.*</[hH][1-9]>是会发生问题的,因为数字不成对也会成功匹配,如<H1><H2>是符合这个模式的,由此引出了回溯引用的使用。
(1)回溯引用的使用
在搜索一段文本的重复出现的单词的时候,显然,在搜索某个单词第二个出现的时,这个单词肯定已经已知了,回溯引用正是允许正则表达式模式引用前面的匹配结果。如果有多重嵌套子表达式,以最外层子表达式开始为第一个子表达式,内层逐层递增。
文本:repeated, and and they
模式:[ ]+(\w+)[ ]+\1
结果:and and
分析:[ ]+匹配一个或多个空格;\w+匹配一个或多个字母数字字符,注意\w是括在括号里的,它是一个子表达式;[ ]+也同理;\1这是一个回溯引用,而它引用的正是前面的第一个子表达式,以此类推,\2 \3表示第二个,第三个。
(2)回溯引用在替换操作中的使用
文本:Hello, ben@forta.com is my email address
模式:(\w+[\w\.]*@[\w\.]+\.\w+)
替换:<a href-"mailto:\1">\1</a>
结果:Hello,<a href="mailto:ben@forta.com">ben@forta.com</a>
分析:替换中的\1是为了引用前面的子表达式,可以看到模式中的子表达式用元字符(和)括起来了。
(3)大小写替换
用来进行大小写转换的元字符:
七、前后查找
到目前为止,我们看到的正则表达式都是用来匹配文本的,但有时我们还需要正则表达式标明要匹配的文本的位置(而不仅仅是文本本身),由此引出前后查找。
(1)向前查找
向前查找指定了一个必须匹配但不在结果中返回的模式。向前查找实际就是要给子表达式。从语法上看,一个向前查找模式其实就是一个以?=开头的子表达式,需要匹配的文本跟在=的后面。
例子:
文本:http://www.forta.com/
模式:.+(?=:)
结果:http
分析:在上面的url地址中,协议名和主机名之间以一个:分隔。.+匹配任意文本;子表达式(?=:)匹配:,但是注意,被匹配到的:并没有出现在最终的匹配结果中。、
我们用?=向正则表达式引擎表明:只要找到:就停止,不把它包括在最终的匹配结果中。
(2)向后查找
向后查找元字符是?<=后面跟着要匹配的字符,和向前查找使用方法类似。