八
11
元字符(Meta character)是正则表达式千变万化的精髓,熟悉各种元字符,也就不难理解和使用正则表达式了。
基本元字符
|
元字符
|
含义
|
说明
|
|
\
|
将下一个字符标记为一个特殊字符、或一个原义字符、或一个后向引用、或一个八进制转义符
|
‘n’ 匹配字符 "n"。‘\n’ 匹配一个换行符。序列 ‘\’ 匹配 "\" 而 "\(" 则匹配 "("
|
|
^
|
匹配字符串的开始
|
|
|
$
|
匹配字符串的结束
|
|
|
*
|
匹配前面的子表达式零次或多次
|
‘zo’ 能匹配 "z" 以及 "zoo"。 * 等价于{0,}
|
|
+
|
匹配前面的子表达式一次或多次
|
‘zo+’ 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}
|
|
?
|
匹配前面的子表达式零次或一次
|
"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于 {0,1}
|
|
{n}
|
匹配n次
|
‘o{2}’ 不能匹配 "Bob" 中的 ‘o’,但是能匹配 "food" 中的两个 o
|
|
{n,}
|
至少匹配n次
|
‘o{2,}’ 不能匹配 "Bob" 中的 ‘o’,但能匹配 "foooood" 中的所有 o。‘o{1,}’ 等价于 ‘o+’。‘o{0,}’ 则等价于 ‘o*’
|
|
{n,m}
|
最少匹配 n 次且最多匹配 m 次
|
"o{1,3}" 将匹配 "fooooood" 中的前三个 o。‘o{0,1}’ 等价于 ‘o?’。请注意在逗号和两个数之间不能有空格
|
|
[]
|
字符集合。匹配所包含的任意一个字符
|
‘[abc]‘ 可以匹配 "plain" 中的 ‘a’。
|
|
[^]
|
反义。匹配未包含的任意字符
|
‘[^abc]‘ 可以匹配 "plain" 中的‘p’
|
|
-
|
字符范围。匹配指定范围内的任意字符
|
‘[a-z]‘ 可以匹配 ‘a’ 到 ‘z’ 范围内的任意小写字母字符。
‘[^a-z]‘ 可以匹配任何不在 ‘a’ 到 ‘z’ 范围内的任意字符
|
|
x|y
|
分支条件。匹配 x 或 y
|
‘z|food’ 能匹配 "z" 或 "food"。‘(z|f)ood’ 则匹配 "zood" 或 "food"
|
|
(pattern)
|
分组(或子表达式)。匹配pattern 并获取这一匹配
|
(\d{1,3}\.){3}\d{1,3}是一个简单的IP地址匹配表达式。要理解这个表达式,请按下列顺序分析它:\d{1,3}匹配1到3位的数字,(\d{1,3}\.){3}匹配三位数字加上一个英文句号(这个整体也就是这个分组)重复3次,最后再加上一个一到三位的数字(\d{1,3})
|
懒惰元字符
当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符。以这个表达式为例:a.*b,它将会匹配最长的以a开始,以b结束的字符串。如果用它来搜索aabab的话,它会匹配整个字符串aabab。这被称为贪婪匹配。
懒惰匹配,也就是匹配尽可能少的字符。当?紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是懒惰的。
|
元字符
|
含义
|
说明
|
|
*?
|
重复任意次,但尽可能少重复
|
字符串 "oooo",‘o+?’ 将匹配单个 "o",而 ‘o+’ 将匹配所有 ‘o’。
a.*?b匹配最短的,以a开始,以b结束的字符串。如果把它应用于aabab的话,它会匹配aab(第一到第三个字符)和ab(第四到第五个字符)
|
|
+?
|
重复1次或更多次,但尽可能少重复
|
|
|
??
|
重复0次或1次,但尽可能少重复
|
|
|
{n,m}?
|
重复n到m次,但尽可能少重复
|
|
|
{n,}?
|
重复n次以上,但尽可能少重复
|
反斜杠元字符
|
元字符
|
含义
|
说明
|
|
\b
|
匹配一个单词边界,也就是指单词和空格间的位置。
|
‘er\b’ 可以匹配"never" 中的 ‘er’,但不能匹配 "verb" 中的 ‘er’
|
|
\B
|
反义。匹配非单词边界
|
‘er\B’ 能匹配 "verb" 中的 ‘er’,但不能匹配 "never" 中的 ‘er’
|
|
\d
|
匹配一个数字
|
等价于 [0-9]
|
|
\D
|
反义。匹配一个非数字
|
等价于 [^0-9]
|
|
\f
|
匹配一个换页符
|
等价于 \x0c 和 \cL
|
|
\n
|
匹配一个换行符
|
等价于 \x0a 和 \cJ
|
|
\r
|
匹配一个回车符
|
等价于 \x0d 和 \cM
‘\n\s*\r’ 匹配空白行
|
|
\s
|
匹配任何空白字符,包括空格、制表符、换页符等
|
等价于 [ \f\n\r\t\v]
|
|
\S
|
反义。匹配任何非空白字符
|
等价于 [^ \f\n\r\t\v]
|
|
\t
|
匹配一个制表符
|
等价于 \x09 和 \cI
|
|
\v
|
匹配一个垂直制表符
|
等价于 \x0b 和 \cK
|
|
\w
|
匹配包括下划线的任何单词字符
|
等价于‘[A-Za-z0-9_]‘
|
|
\W
|
反义。匹配任何非单词字符
|
等价于 ‘[^A-Za-z0-9_]‘
|
|
\0nn
|
匹配ASCII代码用八进制表示的转义值。八进制转义值必须为确定的两个数字长
|
‘\077′ 匹配 "?"
|
|
\xnn
|
匹配ASCII代码用八进制表示的转义值。十六进制转义值必须为确定的两个数字长
|
‘\x41′ 匹配 "A"。‘\x041′ 则等价于 ‘\x04′ & "1"。
‘ [^\x00-\xff] ‘ 匹配双字节字符
|
|
\unnnn
|
匹配Unicode代码中十六进制代码为nnnn的字符
|
‘ [\u4e00-\u9fa5] ‘匹配中文字符
|
|
\e
|
匹配Escape
|
|
|
\cx
|
匹配由x指明的控制字符
|
\cM 匹配一个 Control-M 或回车符。 x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 ‘c’ 字符
|
|
\num
|
对所获取的分组匹配的引用。只有在小括号下面才有\num的引用
|
‘(.)\1′ 匹配两个连续的相同字符。
‘ (.)(.)\1\2′ 匹配4个字符,第一个和第3个相同,第2个和第4个相同,比如dcdc
|
后向引用
后向引用是在分组匹配(小括号部分)基础上提出的,对于分组匹配的每个分组,从左到右自动分配了一个组号1-9。后向引用用于重复搜索前面某个分组匹配的文本。例如,\1代表分组1匹配的文本。
\b(\w+)\b\s+\1\b可以用来匹配重复的单词,像go go, 或者kitty kitty。
|
分类
|
语法
|
说明
|
|
捕获
|
(exp)
|
匹配exp,并捕获文本到自动命名的组里
|
|
(?<name>exp)
|
匹配exp,并捕获文本到名称为name的组里,也可以写成(?’name’exp)
|
|
|
(?:exp)
|
匹配exp,不捕获匹配的文本,也不给此分组分配组号
|
|
|
零宽断言
|
(?=exp)
|
匹配exp前面的位置
|
|
(?<=exp)
|
匹配exp后面的位置
|
|
|
(?!exp)
|
匹配后面跟的不是exp的位置
|
|
|
(?<!exp)
|
匹配前面不是exp的位置
|
|
|
注释
|
(?#comment)
|
这种类型的分组不对正则表达式的处理产生任何影响
|
零度断言
用于查找在某些内容(但并不包括这些内容)之前或之后的东西,也就是说它们像\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)匹配以空白符间隔的数字(再次强调,不包括这些空白符)。
负向零度断言
前面我们提到过怎么查找不是某个字符或不在某个字符类里的字符的方法(反义)。但是如果我们只是想要确保某个字符没有出现,但并不想去匹配它时怎么办?例如,如果我们想查找这样的单词–它里面出现了字母q,但是q后面跟的不是字母u,我们可以尝试这样:
\b\w*q[^u]\w*\b匹配包含后面不是字母u的字母q的单词。但是如果多做测试(或者你思维足够敏锐,直接就观察出来了),你会发现,如果q出现在单词的结尾的话,像Iraq,Benq,这个表达式就会出错。这是因为[^u]总要匹配一个字符,所以如果q是单词的最后一个字符的话,后面的[^u]将会匹配q后面的单词分隔符(可能是空格,或者是句号或其它的什么),后面的\w*\b将会匹配下一个单词,于是\b\w*q[^u]\w*\b就能匹配整个Iraq fighting。负向零宽断言能解决这样的问题,因为它只匹配一个位置,并不消费任何字符。现在,我们可以这样来解决这个问题:\b\w*q(?!u)\w*\b。
零宽度负预测先行断言(?!exp),断言此位置的后面不能匹配表达式exp。例如:\d{3}(?!\d)匹配三位数字,而且这三位数字的后面不能是数字;\b((?!abc)\w)+\b匹配不包含连续字符串abc的单词。
同理,我们可以用(?<!exp),零宽度负回顾后发断言来断言此位置的前面不能匹配表达式exp:(?<![a-z])\d{7}匹配前面不是小写字母的七位数字。
一个更复杂的例子:(?<=<(\w+)>).*(?=<\/\1>)匹配不包含属性的简单HTML标签内里的内容。(<?(\w+)>)指定了这样的前缀:被尖括号括起来的单词(比如可能是<b>),然后是.*(任意的字符串),最后是一个后缀(?=<\/\1>)。注意后缀里的\/,它用到了前面提过的字符转义;\1则是一个反向引用,引用的正是捕获的第一组,前面的(\w+)匹配的内容,这样如果前缀实际上是<b>的话,后缀就是</b>了。整个表达式匹配的是<b>和</b>之间的内容(再次提醒,不包括前缀和后缀本身)。
正则表达式例子
判断Email:
^[a-z0-9_\-]+(\.[_a-z0-9\-]+)*@([_a-z0-9\-]+\.)+([a-z]{2}|aero|arpa|biz|com|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel)$
判断IP:
^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$
判断URL:
^((https?|ftp|news):\/\/)?([a-z]([a-z0-9\-]*\.)+([a-z]{2}|aero|arpa|biz|com|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel)|(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))(\/[a-z0-9_\-\.~]+)*(\/([a-z0-9_\-\.]*)(\?[a-z0-9+_\-\.%=&]*)?)?(#[a-z][a-z0-9_]*)?$
匹配特定数字:
^[1-9]\d*$ //匹配正整数
^-[1-9]\d*$ //匹配负整数
^-?[1-9]\d*$ //匹配整数
^[1-9]\d*|0$ //匹配非负整数(正整数 + 0)
^-[1-9]\d*|0$ //匹配非正整数(负整数 + 0)
^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ //匹配正浮点数
^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ //匹配负浮点数
^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$ //匹配浮点数
^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$ //匹配非负浮点数(正浮点数 + 0)
^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$//匹配非正浮点数(负浮点数 + 0)
匹配特定字符串:
^[A-Za-z]+$//匹配由26个英文字母组成的字符串
^[A-Z]+$//匹配由26个英文字母的大写组成的字符串
^[a-z]+$//匹配由26个英文字母的小写组成的字符串
^[A-Za-z0-9]+$//匹配由数字和26个英文字母组成的字符串
^\w+$//匹配由数字、26个英文字母或者下划线组成的字符串
^[a-zA-Z][a-zA-Z0-9_]{4,15}$ //帐号(字母开头,允许5-16字节,允许字母数字下划线)
资源
正则表达式30分钟入门教程:
ASCII码对照表:
转载本站文章请注明,转载自:神秘果
本文链接: http://www.shenmiguo.com/archives/2009/286_regular-expressions.html

Leave a Reply