正则表达式 初解
来源:互联网 发布:一台电脑开两家淘宝店 编辑:程序博客网 时间:2024/06/04 00:24
1. 元字符及其在正则表达式上下文中的行为:
/ 将下一个字符标记为一个特殊字符、或一个原义字符、或一个后向引用、或一个八进制转义符。
^ 匹配输入字符串的开始位置。如果设置了 RegExp 对象的Multiline 属性,^ 也匹配 ’/n’ 或 ’/r’ 之后的位置。
$ 匹配输入字符串的结束位置。如果设置了 RegExp 对象的Multiline 属性,$ 也匹配 ’/n’ 或 ’/r’ 之前的位置。
* 匹配前面的子表达式零次或多次。
+ 匹配前面的子表达式一次或多次。+ 等价于 {1,}。
? 匹配前面的子表达式零次或一次。? 等价于 {0,1}。
{n} n 是一个非负整数,匹配确定的n 次。
{n,} n 是一个非负整数,至少匹配n 次。
{n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。在逗号和两个数之间不能有空格。
? 当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。
. 匹配除 "/n" 之外的任何单个字符。要匹配包括 ’/n’ 在内的任何字符,请使用象 ’[./n]’ 的模式。
(pattern) 匹配pattern 并获取这一匹配。
(?:pattern) 匹配pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。
(?=pattern) 正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。
(?!pattern) 负向预查,与(?=pattern)作用相反
x|y 匹配 x 或 y。
[xyz] 字符集合。
[^xyz] 负值字符集合。
[a-z] 字符范围,匹配指定范围内的任意字符。
[^a-z] 负值字符范围,匹配任何不在指定范围内的任意字符。
/b 匹配一个单词边界,也就是指单词和空格间的位置。
/B 匹配非单词边界。
/cx 匹配由x指明的控制字符。
/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 为十六进制转义值。十六进制转义值必须为确定的两个数字长。
/num 匹配 num,其中num是一个正整数。对所获取的匹配的引用。
/n 标识一个八进制转义值或一个后向引用。如果 /n 之前至少 n 个获取的子表达式,则 n 为后向引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。
/nm 标识一个八进制转义值或一个后向引用。如果 /nm 之前至少有is preceded by at least 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字符。
1. 捕获组:标志() 若设置了ExplicitCapture选项,则捕获失效
<([a-zA-Z]/d?)>[^<]*<//1>
要匹配的文本 ,表达示中的1表示第一个组,即()中的部分
<p>some Text</p><H2>some heading</H2>
匹配结果:
-------Next Match------
<p>some Text</p>
-------Next Match------
<H2>some heading</H2>
若设置ExplicitCapture
则会报错:
Error:
正在分析“<([a-zA-Z]/d?)>[^<]*<//1>”- 对未定义的组成员 1 的引用。
2. 非捕获(?:)
(?:/d[A-Z])/w
要匹配的字符串: 1A BB SA 1 C
匹配结果:
-------Next Match------
1A
-------Next Match------
BB
-------Next Match------
SA
3.通过名称捕获:(?<name>) 无论是否设定了选项ExplicitCapture,组都将被捕获。
要匹配的字符串:Characters in Seinfeld include Jerry Seinfeld, Elaine Benes, Cosmo Kramer and George Costanza
正则表达示:/b[A-Z][a-z]+ (?<lastName>[A-Z][a-z]+)/b
匹配结果:
-------Next Match------
Jerry Seinfeld
-------Next Match------
Elaine Benes
-------Next Match------
Cosmo Kramer
-------Next Match------
George Costanza
同时也可以根据 ‘姓’访问捕获的组的值
match.Groups["lastName"].Value=Seinfeld
4. 简单捕获
正则表达示:(/d/d)/s([A-Z][A-Z])
匹配字符串:12 AB 34 CD 56 EF
匹配结果:
-------Next Match------
12 AB
-------Next Match------
34 CD
-------Next Match------
56 EF
每一次的匹配结果有两个组对象
也可以将正则表达式改为
(?<numberGroup>/d/d)/s(?<letterGroup>[A-Z][A-Z])
5. 替换:
可以用以下字符来替换文本中的指定的组
字符 用途
$groupNumber 用groupNumber指定的组作替换
${name} 替换由组(?<name>)匹配的最后一个子串
$$ 替换字符$
$& 替换所有的匹配
$+ 替换最后捕获的组
$ 替换整个的输入字符串
例如:
要匹配的文本为:The defendants, who can't be name for legal reasons, were Dr Helen, Ms July.
正则表达式:(?<title>Mr|Mrs|miss|Ms|Dr) [A-Z][a-z]*
替换字符串为:${title} x 或$1 x 或$+ x
结果为:The defendants, who can't be name for legal reasons, were Dr x, Ms x.
若替换字符串为:$&
结果字符串不变。
若替换字符串为:$$ 或
结果为:The defendants, who can't be name for legal reasons, were $, $.
若替换字符串为:(?<title>Mr|Mrs|miss|Ms|Dr) (?<name>[A-Z][a-z]*)
则结果为:The defendants, who can't be name for legal reasons, were Helen, July.
6. 反向引用:
匹配上一个组的语法是/groupNumber 或/k<groupName>
因为有符号 / ,所以在字符串前要加转义字符/.
例如:查找两个单词连续出现的情况:
(?<name>/b[a-zA-Z]+/b)/s/k<name>或(?<name>/b[a-zA-Z]+/b)/s/1
用/k<name> 或 /1 来代替(?<name>/b[a-zA-Z]+/b)
要匹配的文本: in the second quarter quarter , the the stock.
要替换的文本:$1或${name}
结果:in the second quarter , the stock.
7. 正声明:(?=)
(?=)规定了括号中的模式必须出现在声明的右侧。模式将不构成最后匹配的一部分。
要匹配的文本:java, C#.net, VB.net, jscript.net
正则表达式:/S+(?=/.net)
匹配结果:
-------Next Match------
C#
-------Next Match------
VB
-------Next Match------
jscript
即匹配的是‘空格’和‘.net’中间的字符
8. 负声明:(?!)
(?!)规定了模式不能紧邻声明的右侧。模式不构成最终匹配的一部分。
考虑如下的匹配字符串:123A 456c 789 111C
正则表达式:/d{3}(?![A-Z])
匹配结果:
456
789
即匹配的是符合左边的字符串,但不紧邻负声明中的字符串的结果。
9. 反向正声明:(?<=)
(?<=)规定了括号中的模式必须 出现 在声明的左侧。模式不构成最终匹配的一部分。
考虑如下输入字符串:New Mexico, West Virginia Washington, New England.
正则表达式:(?<=New )([A-Z][a-z]+)
匹配结果:
Mesico
England
即匹配的结果是符合反向正声明的右边规则的字符串
10. 反向负声明:(?<!)
(?<!) 规定了模式不能坚信声明的左侧。模式仍然不构成最终匹配的一部分。
考虑如下的输入字符串:
123A 456F 789C 111A
正则表达式:(?<!1)/d{2}[A-Z]
匹配结果:
56F
89C
即匹配的结果是符合反向正声明的右边的规则的字符串,但不能紧邻声明。
11. 非回溯:(?>)
(?>)防止了Regex引擎在失败时回溯(backtracking)以试图匹配,它称为贪婪的子表达式。假设要匹配所有的以“ing”结尾的单词。输入字符串如下:
He was very trusting.
要得到完整的文本,可以使用如下的正则表达式:
.*ing
但是,如果不进行回溯,将无法实现匹配:
(?>*)ing
12. 比较高级组:
要匹配的字符:A1 B 2 C D3 E4
正则表达式 (正声明)[A-Z](?=/d)
匹配结果:
A
D
E
正则表达式 (负声明) [A-Z](?!/d)
匹配结果:
B
C
正则表达式 (反向正声明) (?<=[A-Z])/d
匹配结果为:
1
3
4
正则表达式 (反向负声明)(?=![A-Z])/d
匹配结果为:
2
正则表达式 (回溯) www/.(.*)/.com
要匹配的文本:http://www.wrox.com
第一次匹配结果:www/. + wrox.com + 失败
第二次匹配结果 www/. + wrox.co m 失败
第二次匹配结果 www/. + wrox.c om 失败
第二次匹配结果 www/. + wrox. com 失败
第二次匹配结果 www/. + wrox .com 成功
这样匹配的效率转低:
修改正则表达式为(非回溯)类型:www/.(?>[^/.]*)/.com
这样只需匹配一次。
13. 在正则表达式中作决策
决策指令 (?(expression)yes|no)
若expression得到匹配,则从开始匹配yes表达式 否则匹配no表达式。
但expression并不包含在匹配的结果中
例如:
要匹配的文本:1A CB 3A 5C 3B
正则表达式:(?(/d)A|B)
匹配结果:
-------Next Match------
B
-------Next Match------
B
要匹配的文本:1A CB 3A 5C 3B
正则表达式:(?(/d)/dA|[A-Z]B)
匹配结果:
-------Next Match------
1A
-------Next Match------
CB
-------Next Match------
3A
要匹配的文本:77-77A 69-AA 57-B
正则表达式:(?(/d)/wA|B)
匹配结果:
-------Next Match------
7A
-------Next Match------
B
也可以使用以下语法:(?(name)yes|no)
name指的是前面的捕获组的名称或编号
例如:
要匹配的文本:77-77A 69-AA 57-B
正则表达式:(/d7)?-(?(1)/d/d[A-Z]|[A-Z][A-Z])
其中的(1)表示前面的第一个匹配组(/d7)
匹配结果:
-------Next Match------
77-77A
-------Next Match------
-AA
也可以用前面的匹配组的名称来替换:
例如:
正则表达式:(?<name>/d7)?-(?(name)/d/d[A-Z]|[A-Z][A-Z])
其中的(1)表示前面的第一个匹配组(/d7)
匹配结果:
-------Next Match------
77-77A
-------Next Match------
-AA
14. 在正则表达式内设定选项
例如:(?1:[a-z])
现在无论创建什么正则表达式时全局选项是什么,[a-z]都将匹配大写字母A-Z.如果想删除一个选项,只需要使用符号“-”。例如:使用下面的表达式使匹配区分大小写:(?-i:[a-z])
下表为内联的5个选项:
正则表达式选项 标志 描述
ExplicitCapture N 此选项规定,只有显式命名或编号的组才是有效的捕获
IgnoreCase I 此选项规定不区分大小写的匹配
IgnorePatternWhitespace X 此选项规定,非转义的空字符被排除在模式之外,并启用了前缀一个#的注释
MultiLine M 指定多行模式,修改了字符和^的$含义
SingleLine S 此选项规定,只有显式命名或编号的组才是有效的捕获。
可以一次设定任意多的选项,例如:
(?n-i:[a-z]) 这样就把组设为ExplicitCapture选项并区分大小写。
15. 正则表达式规则:
规则1. 正则表达式引擎会对输入字符串尽快地开始匹配。它一次搜索一个字符,直到发现一次匹配。
例如:
要匹配的字符串:123 ABC 456 DEF
Regex=[A-Z]*
本例从ABC开始匹配。
规则2. 发现一个匹配的开头后,正则表达式引擎将继续匹配,直到一个遇到一个不被模式接收的字符。
要匹配的字符串:123 ABC 456 DEF
Regex=[A-Z]*
本例第一次匹配从ABC,开始,当遇到模式不接受的空格时结束。
规则3. Regex 引擎非常贪婪----只要模式允许,它将匹配尽可能多的字符。
要匹配的字符串:'Dr walson's watch'
Regex='.*'
它的匹配是整个字符串。表达式模式匹配一个单引号,后跟任意字符,然后以另一个单引号结束。所以'Dr Walson'是匹配的,引擎不需要继续匹配其他的字符,它已经有匹配的模式了。但是,正则表达式引擎继续匹配(见规则2----匹配一直进行到出现一个无效字符),并发现还能匹配: s watch'
添加一个“?”,使*成为一个非贪婪的限定符:
Regex='.*?'
这时正则表达式将只匹配:'Dr walson'
规则4: Regex引擎渴望实现匹配,所以将在需要时回溯以实现匹配。
要匹配的文本为:'Hello world' said K & R.
Regex='.*'
匹配结果为:'Hello world'
但是,如果没有回溯操作将无法得到匹配。规则3 说明表达式引擎在寻找安能实现的最大匹配。 .* 表示匹配一个字符0次或多次。所以虽然第一次的'Hello world'已经足够完成匹配。但Regex引擎想实现更多的匹配,并在规则2不适用时继续搜索,直到字符串的末端。结果第一次无法匹配成功。
所以在这里渴望实现匹配的引擎回溯一个字符,直到回溯到world后的“'”,从而完成匹配。使用一个非回溯组禁用回溯操作,会发生下列情况:
要匹配的文本为:'Hello world' said K & R.
Regex='(?>.*)'
因为.*匹配了右侧直到结束的所有字符,而且规定了不使用回溯,所以引擎无法根据'Hello world' 实现匹配。
规则5: Regex引擎总是选择第一个选项
当使用字符“|”指定不能选择时,正则表达式引擎将试图匹配第一个选项,如果无法匹配,再匹配第二个,然后第三个等等。
要匹配的文本为:1234 123 3456
Regex=(/d{2}|/d{3}|/d{4})
16 . 常用验证字符
1> 不包含字母或空格
[^a-zA-Z ]
2> 不包含字母或数字或空格
[^a-zA-Z//d]
3>. 只包含数字
[^//d.]
通常.是一个特殊的正则表达式字符,它可以匹配任何字符,如果要匹配一个真正的“.”,需要将它转义为“/.”。不过,当用方括号来指定匹配的字符时,这就不必要了。
4>. 整数
((/+|-)/d)?/d* 或(/+|-)?/d+
5>. 浮点数
^(/+|-)?/d+(/./d+)?$
浮点数也包括整数。所以“.”后面的数据可有可无。
6>.国内邮政编码:即6位数字 且第一位数不为0 ^[1-9]/d{5}$
7>.国内固电号码 即3至4位区号+“-”或者空格+7至8位本地号码,
或者区号加上“()”后直接加本地号码。
^(/(/d{3,4}/)|/d{3,4}(-|/s))/d{7,8}$
8> 身份证号 是15位或17位后加一数据或“x”;
9> HTML标签
(<[a-zA-Z]+[^>]*>|</[a-zA-Z]+/d*>)
"^/d+$" //非负整数(正整数 + 0)
"^[0-9]*[1-9][0-9]*$" //正整数
"^((-/d+)|(0+))$" //非正整数(负整数 + 0)
"^-[0-9]*[1-9][0-9]*$" //负整数
"^-?/d+$" //整数
"^/d+(/./d+)?$" //非负浮点数(正浮点数 + 0)
"^(([0-9]+/.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*/.[0-9]+)|([0-9]*[1-9][0-9]*))$" //正浮点数
"^((-/d+(/./d+)?)|(0+(/.0+)?))$" //非正浮点数(负浮点数 + 0)
"^(-(([0-9]+/.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*/.[0-9]+)|([0-9]*[1-9][0-9]*)))$" //负浮点数
"^(-?/d+)(/./d+)?$" //浮点数
"^[A-Za-z]+$" //由26个英文字母组成的字符串
"^[A-Z]+$" //由26个英文字母的大写组成的字符串
"^[a-z]+$" //由26个英文字母的小写组成的字符串
"^[A-Za-z0-9]+$" //由数字和26个英文字母组成的字符串
"^/w+$" //由数字、26个英文字母或者下划线组成的字符串
匹配中文字符的正则表达式: [/u4e00-/u9fa5]
匹配双字节字符(包括汉字在内):[^/x00-/xff]