很多人对正则表达式不大了解,的确,一堆符号看起来乱七八糟,但正则表达式在我们的程序中或工作中无处不在,我更喜欢将正则表达式称做字符串匹配表达式。一大堆名词术语我不多讲,下面就一些实例来分析正则表达式:
1、电话号码匹配
中国的电话号码都是区号+号码组成,0开头,区号2到3位数,号码是7到8位数字。于是我们可以简单写成: 0\d{2,3}匹配区号,d{7,8}匹配号码。电话组合也分几种情况,区号-号码,区号空格号码,(区号)号码。要想完全匹配,我们可以写成:\(?0\d{2,3}[) -]?\d{7,8}
解释如下:\代表转义字符,因为要匹配(,于是需要将其转义,即\(匹配(。接着?代表(出现的次数是0次或1次。然后是区号,接着是)空格或者-出现1次或0次,然后接下来是7位号码或8位号码。
看到这里,可能大家肯定会发现这个表达式的不足,例如(01066666666、010)66666666也可以完全匹配,所以我们可以写成0\d{2,3}[ -]?\d{7,8}|\(0\d{2,3}[)]\d{7,8}
注意:这里|符号是或的意思。
2、数组字符传递匹配
假如一段字符串是:windows3ox4,50linux80,90,100 我们要做的工作是匹配数字3和4,5和80,90,100。那么如何书写正则表达式呢? 首先匹配数字,显然可以写成\d+,我们可以分析其他的几个是数字之间有,号,那么可以拆分一下:即开头由数字开始,接着是如数个“,数字”重复而成。所以我们初略写成\d+[,\d+]+,即匹配无数个数字之间夹杂着,号,+代表重复1次或更多次,*代表重复0次或更多次,所以这里也可以写成\d+[,\d+]*,那么要想完全匹配,这里我们就只能加上“或”符号了。于是最终的可以写成\d+[,\d+]+|\d+
3、13\d{9}匹配13后面跟9个数字(中国的手机号)
4、<(\w+)> 查找尖括号括起来的字母或数字(即HTML/XML标签)
表1.常用的元字符
| 代码 |
说明 |
| . |
匹配除换行符以外的任意字符 |
| \w |
匹配字母或数字或下划线或汉字 |
| \s |
匹配任意的空白符 |
| \d |
匹配数字 |
| \b |
匹配单词的开始或结束 |
| ^ |
匹配字符串的开始 |
| $ |
匹配字符串的结束 |
表2.常用的限定符
| 代码/语法 |
说明 |
| * |
重复零次或更多次 |
| + |
重复一次或更多次 |
| ? |
重复零次或一次 |
| {n} |
重复n次 |
| {n,} |
重复n次或更多次 |
| {n,m} |
重复n到m次 |
表3.常用的反义代码
| 代码/语法 |
说明 |
| \W |
匹配任意不是字母,数字,下划线,汉字的字符 |
| \S |
匹配任意不是空白符的字符 |
| \D |
匹配任意非数字的字符 |
| \B |
匹配不是单词开头或结束的位置 |
| [^x] |
匹配除了x以外的任意字符 |
| [^aeiou] |
匹配除了aeiou这几个字母以外的任意字符 |
表4.分组语法
| 捕获 |
| (exp) |
匹配exp,并捕获文本到自动命名的组里 |
| (?exp) |
匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp) |
| (?:exp) |
匹配exp,不捕获匹配的文本,也不给此分组分配组号 |
| 零宽断言 |
| (?=exp) |
匹配exp前面的位置 |
| (?<=exp) |
匹配exp后面的位置 |
| (?!exp) |
匹配后面跟的不是exp的位置 |
| (? |
匹配前面不是exp的位置 |
| 注释 |
| (?#comment) |
这种类型的组不对正则表达式的处理产生任何影响,用于提供注释让人阅读 |
表5.懒惰限定符
| *? |
重复任意次,但尽可能少重复 |
| +? |
重复1次或更多次,但尽可能少重复 |
| ?? |
重复0次或1次,但尽可能少重复 |
| {n,m}? |
重复n到m次,但尽可能少重复 |
| {n,}? |
重复n次以上,但尽可能少重复 |
表6.常用的处理选项
| 名称 |
说明 |
| IgnoreCase(忽略大小写) |
匹配时不区分大小写。 |
| Multiline(多行模式) |
更改^和$的含义,使它们分别在任意一行的行首和行尾匹配,而不仅仅在整个字符串的开头和结尾匹配。(在此模式下,$的精确含意是:匹配\n之前的位置以及字符串结束前的位置.) |
| Singleline(单行模式) |
更改.的含义,使它与每一个字符匹配(包括换行符\n)。 |
| IgnorePatternWhitespace(忽略空白) |
忽略表达式中的非转义空白并启用由#标记的注释。 |
| RightToLeft(从右向左查找) |
匹配从右向左而不是从左向右进行。 |
| ExplicitCapture(显式捕获) |
仅捕获已被显式命名的组。 |
| ECMAScript(JavaScript兼容模式) |
使表达式的行为与它在JavaScript里的行为一致。 |
表7.尚未详细讨论的语法
| \a |
报警字符(打印它的效果是电脑嘀一声) |
| \b |
通常是单词分界位置,但如果在字符类里使用代表退格 |
| \t |
制表符,Tab |
| \r |
回车 |
| \v |
竖向制表符 |
| \f |
换页符 |
| \n |
换行符 |
| \e |
Escape |
| \0nn |
ASCII代码中八进制代码为nn的字符 |
| \xnn |
ASCII代码中十六进制代码为nn的字符 |
| \unnnn |
Unicode代码中十六进制代码为nnnn的字符 |
| \cN |
ASCII控制字符。比如\cC代表Ctrl+C |
| \A |
字符串开头(类似^,但不受处理多行选项的影响) |
| \Z |
字符串结尾或行尾(不受处理多行选项的影响) |
| \z |
字符串结尾(类似$,但不受处理多行选项的影响) |
| \G |
当前搜索的开头 |
| \p{name} |
Unicode中命名为name的字符类,例如\p{IsGreek} |
| (?>exp) |
贪婪子表达式 |
| (?-exp) |
平衡组 |
| (?im-nsx:exp) |
在子表达式exp中改变处理选项 |
| (?im-nsx) |
为表达式后面的部分改变处理选项 |
| (?(exp)yes|no) |
把exp当作零宽正向先行断言,如果在这个位置能匹配,使用yes作为此组的表达式;否则使用no |
| (?(exp)yes) |
同上,只是使用空表达式作为no |
| (?(name)yes|no) |
如果命名为name的组捕获到了内容,使用yes作为表达式;否则使用no |
| (?(name)yes) |
同上,只是使用空表达式作为no |
参考资料: