正则表达式(一)

来源:互联网 发布:origin怎么更新数据 编辑:程序博客网 时间:2024/03/29 23:50

 

 一、什么是正则表达式
Windows/Dos下我们用通配符(wildcard) *?来查找文件,和通配符类似,正则表达式也是用来进行文本匹配的工具,只不过比起通配符,它能更精确地描述你的需求。
正则表达式也是用来进行文本匹配的工具,所以本文里多次提到了在字符串里搜索/查找,意思是在给定的字符串中,寻找与给定的正则表达式相匹配的部分。有可能字符串里有不止一个部分满足给定的正则表达式,这时每一个这样的部分被称为一个匹配。匹配在本文里可能会有三种意思:一种是形容词性的,比如说一个字符串匹配一个表达式;一种是动词性的,比如说在字符串里匹配正则表达式;还有一种是名词性的,就是上面说到的“字符串中满足给定的正则表达式的一部分”。
二、入门
/b是正则表达式规定的一个特殊代码,也叫元字符,代表着单词的开头或者结尾,也就是单词的分界处,它只匹配一个位置。
如果你要找的是hi后面不远处跟着一个Lucy,应该用/bhi/b.*/Lucy/b
*也是元字符,匹配除了换行符以外的任意字符,不过它代表的不是字符,也不是位置,而是数量。它指定*前面的内容以可以联系重复出现任意次以使整个表达式得到匹配。因此,.*连在一起就意味着任意数量的不包含换行的字符。现在/bhi/b.*/Lucy/b的意思就很明显了:先是一个单词hi,然后是任意个字符(但不能是换行),最后是Lucy这个单词。
0/d/d-/d/d/d/d/d/d/d/d匹配这样的字符串:以0开头,然后就是两个数字,然后是一个连字号“-”,最后是8个数字。
/d是一个新的元字符,匹配任意的数字(09)。-不是元字符,只匹配它本身——连字号。也可以简写成:0/d{2}-/d{8}。这里/d后面的{2}({8})意思是前面/d必须连续重复匹配2次(8次)。
1元字符
上节已经介绍了几个元字符/b,.,*,还有/d,当然还有更多的元字符可用,如/s匹配任意的空白符,包括空格,制表符(Tab),换行符,中文全角空格等。/w匹配字母或数字或下划线或汉字等。
下面举几个例子:
/ba/w*/b匹配以字母a开头的单词——先是某个单词开始处(/b,然后是字母a,然后是任意数量的字母或数字(/w*,最后是单词结束处(/b
       /d+匹配1个或更多连续的数字。这里+是和*类似的元字符,不同的是*匹配重复任意次(可能是0),而+则匹配重复1次或更多次。
        /b/w{6}/b匹配刚好6个字母/数字的单词。

1.常用的元字符
代码
说明
.
匹配除换行符以外的任意字符
/w
匹配字母或数字或下划线或汉字
/s
匹配任意的空白符
/d
匹配数字
/b
匹配单词的开始或结束
^
匹配字符串的开始
$
匹配字符串的结束

元字符^以及$/b有点类似,都匹配一个位置。^匹配你要用来查找的字符串的开头,$匹配结尾。这两个代码在验证输入的内容时非常有用,比如一个网站要求你填写的QQ号必须为5位到12位数字时,可以使用:^/d{5,12}$
2字符转义
如果你想查找元字符本身的话,就会出问题。这时就必须使用/来取消这些字符的特殊意义。因此,应该使用//*,如果要查找/本身,就用//
例如:www/.unibetter/.com匹配www.unibetter.com
c://Windows匹配c:/Windows
3重复
你已经看过了前面的*+{2}{5,12}这几个匹配重复的方式了。下面是正则表达式中所有的限定符。

2.常用的限定符
代码/语法
说明
*
重复零次或更多次
+
重复一次或更多次
?
重复零次或一次
{n}
重复n次
{n,}
重复n次或更多次
{n,m}
重复n到m次

下面是一些使用重复的例子:
Windows/d+匹配Windows后面跟1个或更多数字
13/d{9}匹配13后面跟9个数字(中国手机号)
^/w+匹配一行的第一个单词(或整个字符串的第一个单词,具体匹配哪个得看选项设置)
4字符类
如何匹配没有预定义元字符的字符集合(比如元音字母a,e,i,o,u)?
很简单,只需要在中括号中列出它们就行了,像[aeiou]就匹配任何一个英文元音字母,[.?!]匹配标点符号。
也可以指定一个字符范围,像[0-9]代表的含义与/d就是完全一致的:一位小数,同理[a-z0-9A-Z]也完全等用于/w(如果只考虑英文的话)
下面是一个更复杂的表达式:/(?0/d{2}[)-]?/d{8}
这个表达式可以匹配几个格式的电话号码,(010)88886666,或022-22334455,或02912345678,但它也能匹配010)12345678(022-87654321这样的“不正确”的格式。下文讲给出解决这个问题的答案。
5反义
有时需要查找不属于某个能简单定义的字符类的字符。比如想查找除了数字以外,其它任意字符都行的情况,这时就需要反义:

3.常用的反义代码
代码/语法
说明
/W
匹配任意不是字母,数字,下划线,汉字的字符
/S
匹配任意不是空白符的字符
/D
匹配任意非数字的字符
/B
匹配不是单词开头或结束的位置
[^x]
匹配除了x以外的任意字符
[^aeiou]
匹配除了aeiou这几个字母以外的任意字符

例子:/S+匹配不包含空白符的字符串
<a[^>]+>匹配用尖括号括起来的以a开头的字符串
6替换
正则表达式里的替换指的是有几种规则,如果满足其中任意一种规则都应该当成匹配,具体方法是用|把不同的规则分隔开。举例说明:
0/d{2}-/d{8}|0/d{3}-/d{7}这个表达式能匹配两种以连字号分隔的电话号码:一种是三位区号,8位本地号(如025-12345678),一种是4位区号,7位本地号(0510-4567891)。
/(/0d{2}/)[-]?/d{8}|0/d{2}[-]?/d{8} 这个表达式匹配的结果例如(025)-12345678025-1234567802512345678
/d{5}-/d{4}|/d{5}这个表达式用于匹配美国的邮政编码。美国编码规则是5位数字,或者用连字号间隔的9位数字。这个例子还说明一个问题:使用替换时,顺序是很重要的。如果改成/d{5}|/d{5}-/d{4}的话,那么就只会匹配5位的邮政编码以及9位邮编的前5位。因为匹配替换时,将会从左到右地测试每个分支条件,如果满足了某个分支的话,就不会去管其它的替换条件了。
7分组
上面讲到如果想重复多个字符,可以用小括号来指定子表达式(也叫做分组),然后就可以指定这个子表达式的重复次数了。
(/d{1,3}/.){3}/d{1,3}是一个简单的IP地址匹配表达式。分析:/d{1,3}匹配13位的数字,(/d{1,3}/.){3}匹配三位数字加上一个英文句号(这个整体也就是这个分组)重复3次,最后再加上一个13位的数字(/d{1,3})。
但它也将匹配256.300.888.999这种不可能存在的IP地址(IP地址中每个数字都不能大于255)。因为正则表达式中并不提供关于数学的任何功能,所以只能使用冗长的分组,选择,字符类来描述一个正确的IP地址:((2[0-4]/d|25[0-5]|[01]?/d/d?)/.){3}(2[0-4]/d|25[0-5]|[01]?/d/d?)
2[0-4]/d|25[0-5]|[01]?/d/d?进行分析:有三种匹配替换2[0-4]/d12[0-4]04中的任意一位数字,/d0-9任意数字;25[0-5]前两位是25[0-5]05中任意数;[01]?/d/d?01重复1次或者0次,/d0-9任意数字,/d?任意数字重复1次或者0次。
8后向引用
使用小括号指定一个子表达式后,匹配这个子表达式的文本(也就是此分组捕获的内容)可以在表达式或其它程序中作进一步的处理。默认情况下,每个分组会自动拥有一个组号,规则是:从左向右,以分组的左括号为标志,第一次出现的分组的组号为1,第二次为2,以此类推。
后向引用用于重复搜索前面某个分组匹配的文本。例如,/1代表分组1匹配的文本。举例说明:
/b(/w+)/b/s+/1/b可以用来匹配重复出现的单词,像go go,kitty kitty。首先是一个单词,也就是单词开始处和结束处之间的多于一个的字母或数字(/b(/w+)/b),然后是1个或几个空白符(/s+),最后是前面匹配的那个单词(/1)。
你也可以自己指定子表达式的组名。要指定一个子表达式的组名,请使用这样的语法:(?<Word>/w+)或者(?'Word'/w+)),这样就把/w+的组名指定为Word了。要反向引用这个分组捕获的内容,你可以使用/k<Word>,所以上一个例子也可以写成这样:/b(?<Word>/w+)/b/s+/k<Word>/b
使用小括号的时候,还有很多特定用途的语法。下面列出了最常用的一些:

4.分组语法
捕获
(exp)
匹配exp,并捕获文本到自动命名的组里
(?<name>exp)
匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp)
(?:exp)
匹配exp,不捕获匹配的文本,也不给此分组分配组号
零宽断言
(?=exp)
匹配exp前面的位置
(?<=exp)
匹配exp后面的位置
(?!exp)
匹配后面跟的不是exp的位置
(?<!exp)
匹配前面不是exp的位置
注释
(?#comment)
这种类型的组不对正则表达式的处理产生任何影响,用于提供注释让人阅读

我们已经讨论了前两种语法。第三个(?:exp)不会改变正则表达式的处理方式,只是这样的组匹配的内容不会像前两种那样被捕获到某个组里面。
9、零宽断言
接下来的四个用于查找在某些内容(但并不包括这些内容)之前或之后的东西,也就是说它们像/b,^,$那样用于指定一个位置,这个位置应该满足一定的条件(断言),因此它们也被称为零度断言。举例说明:
(?=exp)也叫零度宽正预测先行断言,它断言自身出现的位置的后面能匹配表达式exp。比如/b/w+(?=ing/b),匹配以ing结尾的单词的前面部分(除了ing以外的部分),如查找I'm singing while you're dancing.时,它会匹配sing danc
(?<=exp)也叫零宽度正回顾后发断言,它断言自身出现的位置的前面能匹配的表达式exp。比如(?<=/bre)/w+/b会匹配以re开头的单词的后半部分(除re以外的部分),例如在查找reading a book时,它匹配ading
例如你想要给一个很长的数字中每三位间加一个逗号(当然是从右边加起了),你可以这样查找需要在前面和里面添加逗号的部分:
((?<=/d)/d{3})*/b,用它对1234567890进行查找时结果是234567890
下面这个例子同时使用了这两种断言:(?<=/s)/d+(?=/s)匹配以空白符间隔的数字(不包括这些空白符)。
 
原创粉丝点击