正则表达式的语法(摘自msdn)
字符 | 说明 |
/ | 将下一字符标记为特殊字符、文本、反向引用或八进制转义符。例如,“n”匹配字符“n”。“/n”匹配换行符。序列“//”匹配“/”,“/(”匹配“(”。 |
^ | 匹配输入字符串开始的位置。如果设置了 RegExp 对象的 Multiline 属性,^ 还会与“/n”或“/r”之后的位置匹配。 |
$ | 匹配输入字符串结尾的位置。如果设置了 RegExp 对象的 Multiline 属性,$ 还会与“/n”或“/r”之前的位置匹配。 |
* | 零次或多次匹配前面的字符或子表达式。例如,zo* 匹配“z”和“zoo”。* 等效于 {0,}。 |
+ | 一次或多次匹配前面的字符或子表达式。例如,“zo+”与“zo”和“zoo”匹配,但与“z”不匹配。+ 等效于 {1,}。 |
? | 零次或一次匹配前面的字符或子表达式。例如,“do(es)?”匹配“do”或“does”中的“do”。? 等效于 {0,1}。 |
{n} | n 是非负整数。正好匹配 n 次。例如,“o{2}”与“Bob”中的“o”不匹配,但与“food”中的两个“o”匹配。 |
{n,} | n 是非负整数。至少匹配 n 次。例如,“o{2,}”不匹配“Bob”中的“o”,而匹配“foooood”中的所有 o。'o{1,}' 等效于 'o+'。'o{0,}' 等效于 'o*'。 |
{n,m} | m 和 n 是非负整数,其中 n <= m。至少匹配 n 次,至多匹配 m 次。例如,“o{1,3}”匹配“fooooood”中的头三个 o。'o{0,1}' 等效于 'o?'。注意:您不能将空格插入逗号和数字之间。 |
? | 当此字符紧随任何其他限定符(*、+、?、{n}、{n,}、{n,m})之后时,匹配模式是“非贪心的”。“非贪心的”模式匹配搜索到的、尽可能短的字符串,而默认的“贪心的”模式匹配搜索到的、尽可能长的字符串。例如,在字符串“oooo”中,“o+?”只匹配单个“o”,而“o+”匹配所有“o”。 |
. | 匹配除“/n”之外的任何单个字符。若要匹配包括“/n”在内的任意字符,请使用诸如“[/s/S]”之类的模式。 |
(pattern) | 匹配 pattern 并捕获该匹配的子表达式。可以使用 $0...$9 属性从结果“匹配”集合中检索捕获的匹配。若要匹配括号字符 ( ),请使用“/(”或者“/)”。 |
(?:pattern) | 匹配 pattern 但不捕获该匹配的子表达式,即它是一个非捕获匹配,不存储供以后使用的匹配。这对于用“或”字符 (|) 组合模式部件的情况很有用。例如,与“industry|industries”相比,“industr(?:y| ies)”是一个更加经济的表达式。 |
(?=pattern) | 执行正向预测先行搜索的子表达式,该表达式匹配处于匹配 pattern 的字符串的起始点的字符串。它是一个非捕获匹配,即不能捕获供以后使用的匹配。例如,“Windows (?=95| 98| NT| 2000)”与“Windows 2000”中的“Windows”匹配,但不与“Windows 3.1”中的“Windows”匹配。预测先行不占用字符,即发生匹配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。 |
(?!pattern) | 执行反向预测先行搜索的子表达式,该表达式匹配不处于匹配 pattern 的字符串的起始点的搜索字符串。它是一个非捕获匹配,即不能捕获供以后使用的匹配。例如,“Windows (?!95| 98| NT| 2000)”与“Windows 3.1”中的“Windows”匹配,但不与“Windows 2000”中的“Windows”匹配。预测先行不占用字符,即发生匹配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。 |
x| y | 与 x 或 y 匹配。例如,“z| food”与“z”或“food”匹配。“(z| f)ood”与“zood”或“food”匹配。 |
[xyz] | 字符集。匹配包含的任一字符。例如,“[abc]”匹配“plain”中的“a”。 |
[^xyz] | 反向字符集。匹配未包含的任何字符。例如,“[^abc]”匹配“plain”中的“p”。 |
[a-z] | 字符范围。匹配指定范围内的任何字符。例如,“[a-z]”匹配“a”到“z”范围内的任何小写字母。 |
[^a-z] | 反向范围字符。匹配不在指定的范围内的任何字符。例如,“[^a-z]”匹配任何不在“a”到“z”范围内的任何字符。 |
/b | 匹配一个字边界,即字与空格间的位置。例如,“er/b”匹配“never”中的“er”,但不匹配“verb”中的“er”。 |
/B | 非字边界匹配。“er/B”匹配“verb”中的“er”,但不匹配“never”中的“er”。 |
/cx | 匹配由 x 指示的控制字符。例如,/cM 匹配一个 Control-M 或回车符。x 的值必须在 A-Z 或 a-z 之间。如果不是这样,则假定 c 就是“c”字符本身。 |
/d | 数字字符匹配。等效于 [0-9]。 |
/D | 非数字字符匹配。等效于 [^0-9]。 |
/f | 换页符匹配。等效于 /x0c 和 /cL。 |
/n | 换行符匹配。等效于 /x0a 和 /cJ。 |
/r | 匹配一个回车符。等效于 /x0d 和 /cM。 |
/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_]”等效。 |
/xn | 匹配 n,此处的 n 是一个十六进制转义码。十六进制转义码必须正好是两位数长。例如,“/x41”匹配“A”。“/x041”与“/x04”&“1”等效。允许在正则表达式中使用 ASCII 代码。 |
/num | 匹配 num,此处的 num 是一个正整数。到捕获匹配的反向引用。例如,“(.)/1”匹配两个连续的相同字符。 |
/n | 标识一个八进制转义码或反向引用。如果 /n 前面至少有 n 个捕获子表达式,那么 n 是反向引用。否则,如果 n 是八进制数 (0-7),那么 n 是八进制转义码。 |
/nm | 标识一个八进制转义码或反向引用。如果 /nm 前面至少有 nm 个捕获子表达式,那么 nm 是反向引用。如果 /nm 前面至少有 n 个捕获,那么 n 是反向引用,后面跟 m。如果前面的条件均不存在,那么当 n 和 m 是八进制数 (0-7) 时,/nm 匹配八进制转义码 nm。 |
/nml | 当 n 是八进制数 (0-3),m 和 l 是八进制数 (0-7) 时,匹配八进制转义码 nml。 |
/un | 匹配 n,其中 n 是以四位十六进制数表示的 Unicode 字符。例如,/u00A9 匹配版权符号 (©)。 |
元字符
元字符 | |
代码 | 说明 |
. | 匹配除换行符以外的任意字符 |
/w | 匹配字母或数字或下划线或汉字 |
/s | 匹配任意的空白符 |
/d | 匹配数字 |
/b | 匹配单词的开始或结束 |
^ | 匹配字符串的开始 |
$ | 匹配字符串的结束 |
例子:
/ba/w*/b匹配以字母a开头的单词——先是某个单词开始处(/b),然后是字母a,然后是任意数量的字母或数字(/w*),最后是单词结束处(/b)
字符转义
特殊字符的转义需要用/
例子:www/.unibetter/.com匹配www.unibetter.com,c://Windows匹配c:/Windows
表达重复
限定符 | |
代码/语法 | 说明 |
* | 重复零次或更多次 |
+ | 重复一次或更多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
例子:
Windows/d+匹配Windows后面跟1个或更多数字
13/d{9}匹配13后面跟9个数字(中国的手机号)
^/w+匹配一行的第一个单词
字符集
规定一个范围,
例子:
[aeiou]就匹配
替换
相当于逻辑或 标示是 |
需要注意的是,替换的时候要注意先后顺序。/d{5}-/d{4}|/d{5}和/d{5}|/d{5}-/d{4}的结果完全不一样,匹配替换时,将会从左到右地测试每个分枝条件,如果满足了某个分枝的话,就不会去管其它的替换条件
例子:
/(0/d{2}/)[- ]?/d{8}|0/d{2}[- ]?/d{8}匹配3位区号的电话号码,其中区号可以用小括号括起来,也可以不用,区号与本地号间可以用连字号或空格间隔,也可以没有间隔
Windows98|Windows2000|WindosXP 替换是可以多个的任何一个英文元音字母
/(?0/d{2}[) -]?/d{8}匹配几种格式的电话号码
子表达式(分组)
分组,并且提供反向调用。
例子:
字符类来描述一个正确的IP地址:
((2[0-4]/d|25[0-5]|[01]?/d/d?)/.){3}(2[0-4]/d|25[0-5]|[01]?/d/d?)
反向引用
正则表达式的最重要功能之一是存储匹配的模式的一部分以供以后重新使用的能力。可以通过使用非捕获元字符 ?:、?= 或 ?! 来重写捕获。每个捕获的子匹配项按照它们在正则表达式模式中从左到右出现的顺序存储。缓冲区编号从 1 开始,最多可存储 99 个捕获的子表达式。可以使用 /n 来访问每个缓冲区,其中 n 是标识特定缓冲区的一位或两位十进制数字。同样可以给特定的分组命名。方法有尖括号和引号2种:(?'Word'/w+) (?<Word>/w+)
例子:
(/w+)/s/1捕获文字中的重复错词Is is the cost of of gasoline going up up?
(?<=<(/w+)>).*(?=<///1>)匹配不包含属性的简单HTML标签内里的内容。
分组语法 | |
捕获 | |
(exp) | 匹配exp,并捕获文本到自动命名的组里 |
(?<name>exp) | 匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp) |
(?:exp) | 匹配exp,不捕获匹配的文本,也不给此分组分配组号 |
位置指定 | |
(?=exp) | 匹配exp前面的位置 |
(?<=exp) | 匹配exp后面的位置 |
(?!exp) | 匹配后面跟的不是exp的位置 |
(?<!exp) | 匹配前面不是exp的位置 |
注释 | |
(?#comment) | 这种类型的组不对正则表达式的处理产生任何影响,用于提供注释让人阅读 |
零宽断言&负向零宽断言
(?=exp)零宽度正预测先行断言,它断言自身出现的位置的后面能匹配表达式exp。
(?<=exp)零宽度正回顾后发断言,它断言自身出现的位置的前面能匹配表达式exp。
(?!exp)零宽度负预测先行断言,断言此位置的后面不能匹配表达式exp。
(?<!exp)零宽度正回顾后发断言,断言此位置的前面不能匹配表达式exp。
例子:
/b/w+(?=ing/b),匹配以ing结尾的单词的前面部分(除了ing以外的部分),如查找I'm singing while you're dancing.时,它会匹配sing和danc。
(?<=/bre)/w+/b会匹配以re开头的单词的后半部分(除了re以外的部分),例如在查找reading a book时,它匹配ading。
/b/w*q[^u]/w*/b匹配包含后面不是字母u的字母q的单词(不完整)。但是如果多做测试(或者你思维足够敏锐,直接就观察出来了),你会发现,如果q出现在单词的结尾的话,像Iraq,Benq,这个表达式就会出错。
/b/w*q(?!u)/w*/b可以解决这个问题。
注释
小括号的另一种用途是能过语法(?#comment)来包含注释。例如:
2[0-4]/d(?#200-249)|25[0-5](?#250-255)|[01]?/d/d?(?#0-199)。
一般,各个语言的正则表达式都有“忽略模式里的空白符”选项。
于是,表达式就可以写成如下格式:
(?<= # 断言要匹配的文本的前缀
<(/w+)> # 查找尖括号括起来的字母或数字(即HTML/XML标签)
) # 前缀结束
.* # 匹配任意文本
(?= # 断言要匹配的文本的后缀
<///1> # 查找尖括号括起来的内容:前面是一个"/",后面是先前捕获的标签
) # 后缀结束
贪婪和懒惰的感念
正常表达式的默认是贪婪模式的,比如a.*b,它将会匹配最长的以a开始,以b结束的字符串。如果用它来搜索aabab的话,它会匹配整个字符串aabab。
懒惰匹配,也就是匹配尽可能少的字符。a.*?b匹配最短的,以a开始,以b结束的字符串。如果把它应用于aabab的话,它会匹配aab和
懒惰限定符 | |
*? | 重复任意次,但尽可能少重复 |
+? | 重复1次或更多次,但尽可能少重复 |
?? | 重复0次或1次,但尽可能少重复 |
{n,m}? | 重复n到m次,但尽可能少重复 |
{n,}? | 重复n次以上,但尽可能少重复 |
常见的正则表达式的选项
处理选项 | |
名称 | 说明 |
IgnoreCase(忽略大小写) | 匹配时不区分大小写。 |
Multiline(多行模式) | 更改^和$的含义,使它们分别在任意一行的行首和行尾匹配,而不仅仅在整个字符串的开头和结尾匹配。 |
Singleline(单行模式) | 更改.的含义,使它与每一个字符匹配(包括换行符/n)。 |
IgnorePatternWhitespace(忽略空白) | 忽略表达式中的非转义空白并启用由#标记的注释。 |
RightToLeft(从右向左查找) | 匹配从右向左而不是从左向右进行。 |
ExplicitCapture(显式捕获) | 仅捕获已被显式命名的组。 |
ECMAScript(JavaScript兼容模式) | 使表达式的行为与它在JavaScript里的行为一致。 |
平衡组/递归匹配
注意:这里介绍的平衡组语法是由.Net Framework支持的;其它语言/库不一定支持这种功能,或者支持此功能但需要使用不同的语法。
有时我们需要匹配像( 100 * ( 50 + 15 ) )这样的可嵌套的层次性结构,这时简单地使用/(.+/)则只会匹配到最左边的左括号和最右边的右括号之间的内容(这里我们讨论的是贪婪模式,懒惰模式也有下面的问题)。假如原来的字符串里的左括号和右括号出现的次数不相等,比如( 5 / ( 3 + 2 ) ) ),那我们的匹配结果里两者的个数也不会相等。有没有办法在这样的字符串里匹配到最长的,配对的括号之间的内容呢?
为了避免(和/(把你的大脑彻底搞糊涂,我们还是用尖括号代替圆括号吧。现在我们的问题变成了如何把xx <aa <bbb> <bbb> aa> yy这样的字符串里,最长的配对的尖括号内的内容捕获出来。
这里需要用到以下的语法构造:
(?'group') 把捕获的内容命名为group,并压入堆栈
(?'-group') 从堆栈上弹出最后压入堆栈的名为group的捕获内容,如果堆栈本来为空,则本分组的匹配失败
(?(group)yes|no) 如果堆栈上存在以名为group的捕获内容的话,继续匹配yes部分的表达式,否则继续匹配no部分
(?!) 零宽负向先行断言,由于没有后缀表达式,试图匹配总是失败
如果你不是一个程序员(或者你是一个对堆栈的概念不熟的程序员),你就这样理解上面的三种语法吧:第一个就是在黑板上写一个 "group",第二个就是从黑板上擦掉一个"group",第三个就是看黑板上写的还有没有"group",如果有就继续匹配yes部分,否则就匹配 no部分。
我们需要做的是每碰到了左括号,就在黑板上写一个"group",每碰到一个右括号,就擦掉一个,到了最后就看看黑板上还有没有--如果有那就证明左括号比右括号多,那匹配就应该失败。
< #最外层的左括号
[^<>]* #最外层的左括号后面的不是括号的内容
( ( (?'Open'<) #碰到了左括号,在黑板上写一个"Open"
[^<>]* #匹配左括号后面的不是括号的内容
)+ ( (?'-Open'>) #碰到了右括号,擦掉一个"Open"
[^<>]* #匹配右括号后面不是括号的内容
)+ )* (?(Open)(?!)) #在遇到最外层的右括号前面,判断黑板上还有没有没擦掉的"Open";如果还有,则匹配失败
> #最外层的右括号
平衡组的一个最常见的应用就是匹配HTML,下面这个例子可以匹配嵌套的<div>标签:<div[^>]*>[^<>]*(((?'Open'<div[^>]*>)[^<>]*)+((?'-Open'</div>)[^<>]*)+)*(?(Open)(?!))</div>.
参考:
MTracer
这是一个非常好用的正则表达式测试和生成的工具,貌似是需要注册的,目前我还没有碰到到期的情况,不过,由于他就只是一个exe程序,我查找了注册表,发现一个字段可能跟破解有关,希望后来的使用,如果到期了,可以靠修改这个字段无限次的使用。
HKU/S-1-5-21-1993962763-682003330-839522115-500/Software/RegExLab.com/Regexp Match Tracer/Licence/RunTimes
关于正则表达式的应用
在js中的应用可以去js的api查询RegExp对象。
在java中的应用可以去java api查询Matcher对象。