正则表达式必知必会(修订版)整理教程
Posted 挡路人
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了正则表达式必知必会(修订版)整理教程相关的知识,希望对你有一定的参考价值。
正则表达式必知必会(修订版)整理教程
1. 正则表达式入门
1.1 用途
是一种工具,主要用途是搜索变化多端的文本。匹配 到我们想要的信息。
1.2 使用正则表达式
在线测试工具:http://tool.oschina.net/regex/
2. 匹配单个字符
2.1 匹配纯文本
例子:
文本
Hello,my name is zhaikaishun,please visitmy blog at http://blog.csdn.net/t1dmzks?viewmode=contents
正则表达式
Zhaikaishun
结果
Hello,my name is zhaikaishun,pleasevisit my blog athttp://blog.csdn.net/t1dmzks?viewmode=contents
正则表达式
my
结果
Hello,myname is zhaikaishun,please visit my blog at http://blog.csdn.net/t1dmzks?viewmode=contents
2.1.1 多个匹配结果问题
大多数正则表达式引擎默认匹配第一个匹配,比如这个my,只匹配第一个,但是也有的匹配全部,如何将两个或两个以上的全部找出来呢,在js中使用g,其他的,请参照相关信息
2.1.2字母大小写问题
正则表达式是区分大小写的,Zhaikaishun不匹配zhaikaishun,不过绝大多数是不区分的,例如mysql,javascript不区分大小写,如何让区分大小写的也不区分,有相关的方法,具体问题具体分析,后面也有相关的例子,这里暂时不阐述
2.2 匹配任意字符
文本
Hust
Wust
Whu
Hust1
Whu1
Hust2.zks
Whu.tzgg
正则表达式
Hust
结果
Hust
Wust
Whu
Hust1
Whu1
Hust2.zks
Whu.tzgg
分析:
能将Hust+一个字符给匹配出来,一个 . 代表任何单个字符、字母、数字、甚至是本身,可以组合使用,例如
正则表达式
.u..
匹配结果
Hust
Wust
Whu
Hust1
Whu1
Hust2.zks
Whu.tzgg
分析:能匹配 u的前面一个字符+u+后面两个字符
2.3 匹配特殊字符
使用转义字符\\
例如匹配 . 使用\\. ;匹配\\ 使用 \\\\
2.
3. 匹配一组字符
3.1匹配多个字符中的某一个
使用[] 例如,匹配abc中的某一个字符,可以[abc]
例如 文本
Zhaikaishun like Eating ice creams,but Ican’t eat to much
正则表达式
[Ee]at
结果
Zhaikaishun like Eatingice creams,but I can’t eat to much
分析: [Ee]匹配E或者e,at匹配at
3.2利用字符区间
例如:
[0123456789]可以写成[0-9]
常见合法区间
[A-Z] | 匹配从A到Z的所有大写字母 |
[a-z] | 匹配从a到z的所有小写字母 |
[A-z] | 匹配所有从ASCII字符A到ASCII字符z,中间还包括一些其他的字符,例如],[,/,^等字符,不常用 |
[A-Za-z0-9] | 匹配大写A-Z,小写a-z,数字0-9的任意一个 |
3.3 取非匹配
除了这个字符集合的字符,其他全部匹配
例如[^0-9]只要不是0-9的字符都可以匹配
4. 使用元字符
元字符是在正则表达式的特殊字符
对特殊字符进行转义的方法,使用\\
这里先列出正则表达式所有元字符及其使用方法一览表,方便大家查阅,不理解的可以在看完整个整理即可了解
4.1正则表达式所有元字符及其使用方法一览表
字符 | 描述 |
\\ | 将下一个字符标记为一个特殊字符、或一个原义字符、或一个 后向引用、或一个八进制转义符。例如,'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' 在内的任何字符,请使用象 '[.\\n]' 的模式。 |
(pattern) | 匹配pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在Visual Basic Scripting Edition 中则使用 $0…$9 属性。要匹配圆括号字符,请使用 '\\(' 或 '\\)'。 |
(?:pattern) | 匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 "或" 字符 (|) 来组合一个模式的各个部分是很有用。例如, 'industr(?:y|ies) 就是一个比 'industry|industries' 更简略的表达式。 |
(?=pattern) | 正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如, 'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows 3.1" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。 |
(?!pattern) | 负向预查,在任何不匹配Negative lookahead matches the search string at any point where a string not matching 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 之前至少有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 字符。例如, \\u00A9 匹配版权符号 (?)。 |
5. 重复匹配
5.1有多少个匹配
文本 Hello,MyEmail is abcd@gmail..com ,xiaoming’sEmail is asdw.gmail.magic.com
5.1.1匹配一个或多个字符
使用+,例如为了匹配上述的电子邮箱
正则表达式
\\w+@\\w+\\.\\w+
结果
hello,my email is abcd@gmail.com, ,xiaoming’s Email is .sdw.gmail.magic.com
分析:\\w可以匹配所有的字母和数字(以及下划线_。这个字符在电子邮件中是合法的),第一个\\w+匹配多个字母或数字字符,然后接一个@(@不需要转义),第二个\\w+匹配多个字母或数字字符,\\.匹配一个.(.需要转义,这里才用的\\.)第三个\\w+匹配多个字母或数字字符.
但是这里我们漏掉了asdw.gmail.magic.com,加入要这两个都匹配出来,可以使用[\\w.]+@[\\w.]+\\.\\w+
5.1.2匹配0个或多个字符
使用*即可。和+类似,但是+至少匹配一次,*可以一次也不匹配
5.1.3匹配0个或一个字符
使用元字符?
5.2匹配的重复次数
正则表达式的+、*、?解决了很多问题,但是有时候,我们需要精确到某一个次数,正则表达式提供了一个设置次数的语法
5.2.1匹配一个精确的值
{num}匹配num次,例如
文本 1231234 12345 abcde abcedf
正则表达式:\\w{5}
结果:123 1234 12345 abcde abce5f
5.2.2为重复匹配设定一个区间
{num1,num2}匹配num1次到num2次之间,例如
文本:aa11aa,aa1aa,bb111bb,bb1111aa
正则表达式:[0-9]{2,4}
结果:aa11aa,aa1aa,bb111bb,bb1111aa
5.2.3匹配至少重复多少次
{num,}例如:
文本: 123 1234 12345 abcde,abcedfabcdefghijk
正则表达式: \\w{4,}
结果: 123 1234 12345 abcde abcedf,abcedfabcdefghijk
5.3防止匹配过渡
?只能匹配一个字符,{n}和{m,n}也有一个重复次数的上限但是对于其他的,例如+、*等没有一个上限,有时候就会导致过渡匹配的情况,例如下面这个例子
文本: Learn English is important,but in <b>CH</b>AND<b>JP<b>,the teachingis not available.
正则表达式:<[Bb]>.* </[Bb]>
结果: Learn English is important,but in <b>CH</b>AND<b>JP<b>,theteaching is not available.
分析:显然,这个.*把第第二个</b>和第三个<b>都给一网打尽,虽然没有漏掉我们所需要的文本,但是,这两个b却莫名失踪了,还多匹配了一个and
为什么会这样呢,是因为*和+都是“贪婪型”元字符,他们在进行匹配时是多多益善的而不是适可而止的。
解决办法:使用这些元字符的“懒惰型”版本,使其匹配尽可能的少,
常见的贪婪型元字符和他们的懒惰型版本
贪婪型元字符 | 懒惰型元字符 |
* | *? |
+ | +? |
{n,} | {n,}? |
比如刚才那个例子
正则表达式:<[Bb]>.*?</[Bb]>
结果:LearnEnglish is important,but in <b>CH</b>AND<b>JP<b>,theteaching is not available.
6.匹配位置
6.1单词边界:
限定符\\b指定单词边界,b是英文boundary(边界)的首字母,例如
文本:The catscattered his food all over the room.
正则表达式:cat
结果: The cat scatteredhis food all over the room.
正则表达式:\\bcat\\b
结果: The cat scattered his food all overthe room.
如果想不匹配一个单词的边界(),使用\\B ,例如下面的例子匹配多余的空格
文本: please enter the nine-digit id as it appears on your color – cpdedpass-key
正则表达式:\\B-\\B
结果:please enter the nine-digit id as it appears on your color– cpded pass-key
分析:\\B-\\B
将匹配一个前后都不是单词边界的连字符(因为空格和连字符都不是字母数字或下划线)。只有color – cpded中的连字符可以与之匹配
6.2字符串边界
6.2.1匹配字符串开头
在第三章节中,我们知道使用^可以用来取非,其实他还有匹配一个字符串的开头
当^出现在一个字符集合中(被放到[和]之间)并且紧跟在左方括号[的后面是,才能发挥“求非”作用。如果是在一个字符集合的外面并且位于一个模式的开头,^将匹配字符串的开头。例如,下面的测试可以检查一个文档是否为xml文档(xml文档必须是<?xmlversion="1.0"?>类型,而且必须放在开头)
文本: this is not a xml document, real not a xmldocument
<?xmlversion="1.0"ecoding=”utf-8” ?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML1.1//EN" " >
<wml>
<head>
<access/>
正则表达式:<\\?xml.*\\?>
结果:this is not a xml document, real not a xmldocument
<?xmlversion="1.0"ecoding=”utf-8” ?>
<!DOCTYPEwml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" " >
<wml>
<head>
<access/>
我们就以为这是xml文件了,其实这不是xml文件,xml文件必须是在开头有上述标示才行
正确的正则表达式:^\\s*<\\?xml.*?\\?>
6.2.2匹配字符串结尾
使用$即可
6.2.3分行匹配
(?m)说明是分行模式,必须出现在整个模式的最前面,下例将会找出所有的注释文章
文本:
String author()default "aaa";
//aaaaaaa
int[]arrayAttr() default {1};
//bbbbbbbb
MetaAnnotation annotationAttr() default@MetaAnnotation("");
//ccccccc
Class<PersonChiness> classType()default PersonChiness.class;
正则表达式:(?m)^\\s*//.*$
结果:Stringauthor() default "aaa";
//aaaaaaa
int[]arrayAttr() default {1};
//bbbbbbbb
MetaAnnotation annotationAttr() default@MetaAnnotation("");
//ccccccc
Class<PersonChiness> classType()default PersonChiness.class;
警告:有许多正则表达式不支持(?m)
7.使用子表达式
7.1子表达式
子表达式是一个更大的表达式的一部分,把一个表达式分解成一系列子表达式的目的就是为了把那些子表达式当做一个独立元素来使用。子表达式必须用()括起来
例如 {2,}只能匹配 ;;;这样的文本
只有( )(2,)才能匹配 这样的文本( )是一个子表达式,它将被视为一个独立元素,而紧跟在它后面的{2,}将作用于这个子表达式
例如我们想要匹配一个年份,|是或的意思
文本 1949-05-10
正则表达式19|20\\d{2}
结果:1949-05-10
因为上述表达式
匹配19或者20后面再加连个数字,自然就匹配到了19
正则表达式
(19|20)d{2}
结果1949-05-10
7.2子表达式的嵌套
子表达式允许嵌套,这样可以构造出功能强大的正则表达式来,但是这种嵌套最好遵循适可而止的原则,不然太复杂也看不懂.
如果我们要匹配一个合法的IP地址,首先我们得把规则列举出来
类似于255.255.255.255
这里有4个模块。对于每一个模块,有以下几个规则
l 任何一个1位或者2位的数字
l 任何一个以1开头的3为数字
l 任何一个以2开头,第二位在0-4之间的三位数字
l 任何一个以25开头,第三位在0-5的三位数字
正则表达式:
(((\\d{1,2})|(1\\d{2})|(2[0-4]\\d)|(25[0-5]))\\.){3}((\\d{1,2})|(1\\d{2})|(2[0-4]\\d)|(25[0-5]))
以上是关于正则表达式必知必会(修订版)整理教程的主要内容,如果未能解决你的问题,请参考以下文章