最重要的是请给我30分钟如果你没有使用正则表达式的经验请不要试图在30秒内入门除非你是超人:)
别被下面那些复杂的表达式吓倒只要跟着我一步一步来你会发现正则表达式其实并没有你想像中的那么困难当然如果你看完了这篇教程之后发现自己明白了很多却又几乎什么都记不得那也是很正常的我认为没接触过正则表达式的人在看完这篇教程后能把提到过的语法记住80%以上的可能性为零这里只是让你明白基本的原理以后你还需要多练习多使用才能熟练掌握正则表达式
除了作为入门教程之外本文还试图成为可以在日常工作中使用的正则表达式语法参考手册就作者本人的经历来说这个目标还是完成得不错的你看我自己也没能把所有的东西记下来不是吗
清除格式文本格式约定专业术语元字符/语法格式正则表达式正则表达式中的一部分(用于分析)对其进行匹配的源字符串对正则表达式或其中一部分的说明
隐藏边注本文右边有一些注释主要是用来提供一些相关信息或者给没有程序员背景的读者解释一些基本概念通常可以忽略正则表达式到底是什么东西
字符是计算机软件处理文字时最基本的单位可能是字母数字标点符号空格换行符汉字等等字符串是0个或更多个字符的序列文本也就是文字字符串说某个字符串匹配某个正则表达式通常是指这个字符串里有一部分或几部分分别能满足表达式给出的条件
在编写处理字符串的程序或网页时经常会有查找符合某些复杂规则的字符串的需要正则表达式就是用于描述这些规则的工具换句话说正则表达式就是记录文本规则的代码
很可能你使用过Windows/Dos下用于文件查找的通配符(wildcard)也就是*和?如果你想查找某个目录下的所有的Word文档的话你会搜索*.doc在这里*会被解释成任意的字符串和通配符类似正则表达式也是用来进行文本匹配的工具只不过比起通配符它能更精确地描述你的需求当然代价就是更复杂比如你可以编写一个正则表达式用来查找所有以0开头后面跟着2-3个数字然后是一个连字号-最后是7或8位数字的字符串(像010-12345678或0376-7654321)入门
学习正则表达式的最好方法是从例子开始理解例子之后再自己对例子进行修改实验下面给出了不少简单的例子并对它们作了详细的说明
假设你在一篇英文小说里查找hi你可以使用正则表达式hi
这几乎是最简单的正则表达式了它可以精确匹配这样的字符串由两个字符组成前一个字符是h,后一个是i通常处理正则表达式的工具会提供一个忽略大小写的选项如果选中了这个选项它可以匹配hi,HI,Hi,hI这四种情况中的任意一种
不幸的是很多单词里包含hi这两个连续的字符比如him,history,high等等用hi来查找的话这里边的hi也会被找出来如果要精确地查找hi这个单词的话我们应该使用\bhi\b
\b是正则表达式规定的一个特殊代码好吧某些人叫它元字符metacharacter代表着单词的开头或结尾也就是单词的分界处虽然通常英文的单词是由空格标点符号或者换行来分隔的但是\b并不匹配这些单词分隔字符中的任何一个它只匹配一个位置
如果需要更精确的说法\b匹配这样的位置它的前一个字符和后一个字符不全是(一个是,一个不是或不存在)\w
假如你要找的是hi后面不远处跟着一个Lucy你应该用\bhi\b.*\bLucy\b
这里.是另一个元字符匹配除了换行符以外的任意字符*同样是元字符不过它代表的不是字符也不是位置而是数量它指定*前边的内容可以连续重复使用任意次以使整个表达式得到匹配因此.*连在一起就意味着任意数量的不包含换行的字符现在\bhi\b.*\bLucy\b的意思就很明显了先是一个单词hi,然后是任意个任意字符(但不能是换行)最后是Lucy这个单词
换行符就是'\n',ASCII编码为10(十六进制0x0A)的字符
如果同时使用其它元字符我们就能构造出功能更强大的正则表达式比如下面这个例子
0\d\d-\d\d\d\d\d\d\d\d匹配这样的字符串以0开头然后是两个数字然后是一个连字号-最后是8个数字(也就是中国的电话号码当然这个例子只能匹配区号为3位的情形)
这里的\d是个新的元字符匹配一位数字(0或1或2或)-不是元字符只匹配它本身连字符(或者减号或者中横线或者随你怎么称呼它)
为了避免那么多烦人的重复我们也可以这样写这个表达式0\d{2}-\d{8}这里\d后面的{2}({8})的意思是前面\d必须连续重复匹配2次(8次)测试正则表达式
其它可用的测试工具:
如果你不觉得正则表达式很难读写的话要么你是一个天才要么你不是地球人正则表达式的语法很令人头疼即使对经常使用它的人来说也是如此由于难于读写容易出错所以找一种工具对正则表达式进行测试是很有必要的
不同的环境下正则表达式的一些细节是不相同的本教程介绍的是微软.NetFramework2.0下正则表达式的行为所以我向你介绍一个.Net下的工具首先你确保已经安装了.NetFramework2.0然后这是个绿色软件下载完后打开压缩包,直接运行RegexTester.exe就可以了
下面是RegexTester运行时的截图
元字符
现在你已经知道几个很有用的元字符了如\b,.,*还有\d.正则表达式里还有更多的元字符比如\s匹配任意的空白符包括空格制表符(Tab)换行符中文全角空格等\w匹配字母或数字或下划线或汉字等
对中文/汉字的特殊处理是由.Net提供的正则表达式引擎支持的其它环境下的具体情况请查看相关文档
下面来看看更多的例子
\ba\w*\b匹配以字母a开头的单词先是某个单词开始处(\b)然后是字母a,然后是任意数量的字母或数字(\w*)最后是单词结束处(\b)
好吧现在我们说说正则表达式里的单词是什么意思吧就是不少于一个的连续的\w不错这与学习英文时要背的成千上万个同名的东西的确关系不大:)
\d+匹配1个或更多连续的数字这里的+是和*类似的元字符不同的是*匹配重复任意次(可能是0次)而+则匹配重复1次或更多次
\b\w{6}\b匹配刚好6个字符的单词表1.常用的元字符代码说明.匹配除换行符以外的任意字符\w匹配字母或数字或下划线或汉字\s匹配任意的空白符\d匹配数字\b匹配单词的开始或结束^匹配字符串的开始$匹配字符串的结束
正则表达式引擎通常会提供一个测试指定的字符串是否匹配一个正则表达式的方法如JavaScript里的RegExp.test()方法或.NET里的Regex.IsMatch()方法这里的匹配是指是字符串里有没有符合表达式规则的部分如果不使用^和$的话对于\d{5,12}而言使用这样的方法就只能保证字符串里包含5到12连续位数字而不是整个字符串就是5到12位数字
元字符^和数字6在同一个键位上的符号和$都匹配一个位置这和\b有点类似^匹配你要用来查找的字符串的开头$匹配结尾这两个代码在验证输入的内容时非常有用比如一个网站如果要求你填写的QQ号必须为5位到12位数字时可以使用^\d{5,12}$
这里的{5,12}和前面介绍过的{2}是类似的只不过{2}匹配只能不多不少重复2次{5,12}则是重复的次数不能少于5次不能多于12次否则都不匹配
因为使用了^和$所以输入的整个字符串都要用来和\d{5,12}来匹配也就是说整个输入必须是5到12个数字因此如果输入的QQ号能匹配这个正则表达式的话那就符合要求了
和忽略大小写的选项类似有些正则表达式处理工具还有一个处理多行的选项如果选中了这个选项^和$的意义就变成了匹配行的开始处和结束处字符转义
如果你想查找元字符本身的话比如你查找.,或者*,就出现了问题你没办法指定它们因为它们会被解释成别的意思这时你就得使用\来取消这些字符的特殊意义因此你应该使用\.和\*当然要查找\本身你也得用\\.
例如unibetter\.com匹配unibetter.comC:\\Windows匹配C:\Windows重复
你已经看过了前面的*,+,{2},{5,12}这几个匹配重复的方式了下面是正则表达式中所有的限定符(指定数量的代码例如*,{5,12}等)表2.常用的限定符代码/语法说明*重复零次或更多次+重复一次或更多次?重复零次或一次{n}重复n次{n,}重复n次或更多次{n,m}重复n到m次
下面是一些使用重复的例子
Windows\d+匹配Windows后面跟1个或更多数字
^\w+匹配一行的第一个单词(或整个字符串的第一个单词具体匹配哪个意思得看选项设置)字符类
要想查找数字字母或数字空白是很简单的因为已经有了对应这些字符集合的元字符但是如果你想匹配没有预定义元字符的字符集合(比如元音字母a,e,i,o,u),应该怎么办
很简单你只需要在方括号里列出它们就行了像[aeiou]就匹配任何一个英文元音字母[.?!]匹配标点符号(.或?或!)
我们也可以轻松地指定一个字符范围像[0-9]代表的含意与\d就是完全一致的一位数字同理[a-z0-9A-Z_]也完全等同于\w如果只考虑英文的话
下面是一个更复杂的表达式\(?0\d{2}[)-]?\d{8}
(和)也是元字符后面的分组节里会提到所以在这里需要使用
这个表达式可以匹配几种格式的电话号码像(010)88886666或022-22334455或02912345678等我们对它进行一些分析吧首先是一个转义字符\(,它能出现0次或1次(?),然后是一个0后面跟着2个数字(\d{2})然后是)或-或空格中的一个它出现1次或不出现(?)最后是8个数字(\d{8})分枝条件
不幸的是刚才那个表达式也能匹配010)12345678或(022-87654321这样的不正确的格式要解决这个问题我们需要用到分枝条件正则表达式里的分枝条件指的是有几种规则如果满足其中任意一种规则都应该当成匹配具体方法是用|把不同的规则分隔开听不明白没关系看例子
0\d{2}-\d{8}|0\d{3}-\d{7}这个表达式能匹配两种以连字号分隔的电话号码一种是三位区号8位本地号(如010-12345678)一种是4位区号7位本地号(0376-2233445)
\(0\d{2}\)[-]?\d{8}|0\d{2}[-]?\d{8}这个表达式匹配3位区号的电话号码其中区号可以用小括号括起来也可以不用区号与本地号间可以用连字号或空格间隔也可以没有间隔你可以试试用分枝条件把这个表达式扩展成也支持4位区号的
0 评论:
发表评论