正则表达式 初解

来源:互联网 发布:一台电脑开两家淘宝店 编辑:程序博客网 时间: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]

 

原创粉丝点击