正则表达式(regular expression)描述了一种字符串匹配模式,由普通字符以及特殊字符(称为"元字符")组成,模式描述在搜索文本时要匹配一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配,是一个非常强大又好用的“工具”,可以用于诸如python爬虫、java开发中进行数据验证,支持跨编程语言使用,如C#、Java、JavaScript、Python、Ruby等,还可以搜索、替换、删除文档中特定的字符串,功能强大,使用灵活。下面总结一些常用的正则表达式语法规则:
(一)普通字符
1.大写字母、小写字母、数字、标点符号
2.非打印字符
\cx:匹配由x指明的控制字符,x 的值必须为 A-Z 或 a-z 之一
\f:匹配一个换页符
\n:匹配一个换行符
\r:匹配一个回车符
\s:匹配任何空白字符,包括空格、制表符、换页符等
\S:匹配任何非空白字符
\d:匹配任何一个数字
\D:匹配任何一个非数字
\w:匹配包括下划线的任何单词字符。等价于''[A-Za-z0-9_]''
\W:匹配任何非单词字符。等价于 ''[^A-Za-z0-9_]''
\t:匹配一个制表符
\v:匹配一个垂直制表符
(二)特殊字符(元字符)
特殊字符,即有一些特殊含义的字符,也叫元字符。匹配这些字符时,要先进行转义再匹配,转义的方法就是在元字符前加反斜杠“\”。如使用 runo\*ob 匹配 runo*ob。常见的特殊字符如下:
^:匹配输入字符串的开始位置
$:匹配输入字符串的结尾位置
( ):标记一个子表达式的开始和结束位置
.:匹配除换行符 \n 之外的任何单字符
?:1)匹配前面的子表达式零次或一次;2)该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 "oooo",''o+?'' 将匹配单个 "o",而 ''o+'' 将匹配所有 ''o'',(''o*?''什么都匹配不到)
*:匹配前面的子表达式零次或多次
+:匹配前面的子表达式一次或多次
\:将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符
[:标记一个中括号表达式的开始
{:标记限定符表达式的开始
|:指明两项之间的一个选择
中括号表达式:
[xyz] :字符集合,匹配所包含的任意一个字符。例如, [abc]?可以匹配 "plain" 中的 ''a
[^xyz] :负值字符集合,匹配未包含的任意字符。例如, [^abc]?可以匹配 "plain" 中的''p''、''l''、''i''、''n''
[a-z] :字符范围,匹配指定范围内的任意字符。例如,[a-z]''可以匹配 ''a'' 到 ''z'' 范围内的任意小写字母字符
[^a-z]:负值字符范围,匹配任何不在指定范围内的任意字符。例如,[^a-z]可以匹配任何不在 ''a'' 到 ''z'' 范围内的任意字符
若要在中括号包含连字符,用转义符合转义:[\-],若匹配所有小写字母和连字符,将连字符放在中括号列表的开始或结尾:[-a-z]或[a-z-],匹配任何大写或小写字母或任何数字的匹配,使用表达式:[A-Za-z0-9]
(三)限定字符
限定符用来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。有 * 或 + 或 ? 或 {n} 或 {n,} 或 {n,m} 共6种。正则表达式的限定符有:
*:匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}
+:匹配前面的子表达式一次或多次。例如,zo+能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}
?:匹配前面的子表达式零次或一次。例如,do(es)? 可以匹配 "do" 或 "does" 中的 "does" 或 "doxy" 中的 "do" 。? 等价于 {0,1}
{n}:n 是一个非负整数。匹配确定的 n 次。
{n,} :n 是一个非负整数。至少匹配n 次。例如,o{2,} 不能匹配 "Bob" 中的 ''o'',但能匹配 "foooood" 中的所有 o
{n,m}:m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,o{1,3} 将匹配 "fooooood" 中的前三个 o
举例:
1)匹配章节标题的正则表达式
任意位数的章节标题: ? ?Chapter [1-9][0-9]*
只有99章: ???Chapter [1-9][0-9]?/ ?或 ?/Chapter [1-9][0-9]{0,1}
2)<H1>Chapter 1 - 介绍正则表达式</H1>
贪婪模式,从开始小于符号 (<) 到关闭 H1 标记的大于符号 (>) 之间的所有内容: ??<.*>
非贪婪,匹配开始和结束 H1 标签,下面的非贪婪表达式只匹配 <H1>:? <.*?>
匹配开始的 H1 标签,表达式则是: ??<\w+?>
(四)定位符
定位符用来描述字符串或单词的边界,^ 和 $ 分别指字符串的开始与结束,\b 描述单词的前或后边界,\B 表示非单词边界。
正则表达式的定位符有:
^:匹配输入字符串开始的位置
$:匹配输入字符串结尾的位置
\b :匹配一个字边界,即字与空格间的位置。
\B :非字边界匹配
若要匹配一行文本开始处的文本,在正则表达式的开始使用 ^ 字符;若要匹配一行文本的结束处的文本,在正则表达式的结束处使用 $ 字符。匹配字边界稍有不同,字边界是单词和空格之间的位置,非字边界是任何其他位置。\b 字符的位置是非常重要的,如果它位于要匹配的字符串的开始,它在单词的开始处查找匹配项。如果它位于字符串的结尾,它在单词的结尾处查找匹配项。
不能将限定符与定位符一起使用。由于在紧靠换行或者字边界的前面或后面不能有一个以上位置,因此不允许诸如 ^* 之类的表达式。
例如匹配章节标题使用正则表达式^Chapter [1-9][0-9]{0,1}$,匹配单词Chapter 的开头三个字符使用表达式:\bCha,匹配单词 Chapter 中的字符串 ter使用表达式:ter\b,另外\Bapt匹配 Chapter 中的字符串 apt,但不匹配 aptitude 中的字符串 apt。
(五)捕获组
捕获组就是把正则表达式中子表达式匹配的内容,保存到内存中以数字编号或显式命名的组里,方便后面引用。当然,这种引用既可以是在正则表达式内部,也可以是在正则表达式外部。捕获组有两种形式,一种是普通捕获组,另一种是命名捕获组,普通捕获组在大多数支持正则表达式的语言或工具中都是支持的,而命名捕获组目前只有.NET、PHP、Python等部分语言支持。通常所说的捕获组指的是普通捕获组。语法如下:
普通捕获组:(Expression)
命名捕获组:(?<name>Expression)
捕获组编号规则:
普通捕获组:普通捕获组的编号是按照“(”出现的顺序,从左到右,从1开始进行编号的 。
命名捕获组:命名捕获组通过显式命名,可以通过组名方便的访问到指定的组,而不需要去一个个的数编号,同时避免了在正则表达式扩展过程中,捕获组的增加或减少对引用结果导致的不可控。同时,命名捕获组也参与了编号的,在只有命名捕获组的情况下,捕获组的编号也是按照“(”出现的顺序,从左到右,从1开始进行编号的 。
普通捕获组和命名捕获组混合编号:混合方式的捕获组编号,首先按照普通捕获组中“(”出现的先后顺序,从左到右,从1开始进行编号,当普通捕获组编号完成后,再按命名捕获组中“(”出现的先后顺序,从左到右,接着普通捕获组的编号值继续进行编号。
关于捕获组,更加详细的介绍请参考http://blog.csdn.net/lxcnn/article/details/4146148
(六)非捕获组
非获取匹配,也就是说,该匹配不进行存储供以后使用
(?:pattern) :匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,例如, ''industr(?:y|ies)?''就是一个比 ''industry|industries'' 更简略的表达式
(?=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"
(七)反向引用
普通捕获组反向引用:\k<number>,通常简写为\number
命名捕获组反向引用:\k<name>或者\k''name''
普通捕获组反向引用中number是十进制的数字,即捕获组的编号;命名捕获组反向引用中的name为命名捕获组的组名。例如:对于正则表达式([ab])\1,匹配的是两个相同的字符,在这里也就是“aa”或者“bb”才能匹配成功。([a-z])\1{2}表达连续三个相同的小写字母。
下面举两个例子,帮助大家更好地理解正则表达式的语法规则——
1)写出正则表达式,从一个字符串中提取链接地址,字符串为:
"IT面试题博客中包含很多 <a href=http://hi.baidu.com/mianshiti/blog/category> 微软面试题 </a>",
需要提取的地址为:" http://hi.baidu.com/mianshiti/blog/category",
参考答案为: ??http(s)?://([\w]+\.)+\w+(/\w+)*
2)在网易注册邮箱时,@符号前的内容有限制:6~18个字符,包括字母、数字、下划线,以字母开头,字母或数字结尾
参考答案为: ??\b[a-zA-Z][0-9a-zA-Z_]{4,16}[0-9a-zA-Z]\b
3)将下面的 URI 分解为协议(ftp、http 等等)、域地址和页/路径:
http://www.runoob.com:80/html/html-tutorial.html
参考答案为:(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)
第一个括号子表达式捕获 Web 地址的协议部分。该子表达式匹配在冒号和两个正斜杠前面的任何单词。匹配到内容为"http"。
第二个括号子表达式捕获地址的域地址部分。子表达式匹配 / 和 : 之外的一个或多个字符。匹配到内容为"www.runoob.com"。
第三个括号子表达式捕获端口号(如果指定了的话)。该子表达式匹配冒号后面的零个或多个数字。只能重复一次该子表达式。匹配到内容为":80"。
最后,第四个括号子表达式捕获 Web 地址指定的路径和 / 或页信息。该子表达式能匹配不包括 # 或空格字符的任何字符序列。匹配到内容为"/html/html-tutorial.html"。
转自网络