唐读笔记-正则表达式必知必会

一、匹配单个字符

1.1、匹配纯文本

Ben纯文本,匹配原始文本Hello, my name is Ben. Please visit my website at http://www.forta.com/.
my纯文本,匹配原始文本中多个结果Hello, my name is Ben. Please visit my website at http://www.forta.com/.

匹配数量:根据正则表达式引擎确认返回第一个还是返回多个

大小写区分:正则表达式是区分字母大小写的

 1.2、匹配任意字符

表1-2-1 任意字符元字符
元字符说明备注
.匹配任意单个字符不能匹配空白元字符
sales.匹配单个sales1.xls
orders3.xls
sales2.xls
sales3.xls
apac1.xls
europe2.xls
na1.xls
na2.xls
sa1.xls
.a.sales1.xls
orders3.xls
sales2.xls
sales3.xls
apac1.xls
europe2.xls
na1.xls
na2.xls
sa1.xls

1.3、匹配特殊字符

【\.】对特殊字符.进行转义,匹配原始字符.

表1-3-1 特殊字符元字符
元字符说明
\对特殊字符进行转义\.对.进行转义
正则表达式说明结果
.a.\.xls对第三个.进行转义操作sales1.xls
orders3.xls
sales2.xls
sales3.xls
apac1.xls
europe2.xls
na1.xls
na2.xls
sa1.xls

二、匹配一组字符

2.1、 匹配多个字符中的某一个

表2-1 字符集合元字符
元字符说明转义
[]使用[和]定义一个字符集合,字符集合的匹配结果是能否与该集合中的任意一个成员相匹配\[和\]
[ns]a.\.xls匹配字符n或s(但不匹配c或其他字符)sales1.xls
orders3.xls
sales2.xls
sales3.xls
apac1.xls
europe2.xls
na1.xls
na2.xls
sa1.xls

ca1.xls
[Re]eg[Ee]x[Rr]负责匹配R或r,[Ee]负责匹配E或eThe phrase "regular expression" is often abbreviated as RegEx or regex.

2.2、利用字符集合区间

表2-2 字符集合区间元字符
元字符说明转义
-为简化使用频繁的字符区间(0~9,A~Z等),正则表达式提供了一个特殊的元字符【-】,字符区间可以用连字符来定义
[ns]a[0-9]\.xls[0-9]等同于[0123456789]sales1.xls
orders3.xls
sales2.xls
sales3.xls
apac1.xls
europe2.xls
na1.xls
na2.xls
sa1.xls

ca1.xls

[A-Z]匹配从A到Z的所有大写字母,a-z匹配从a到z的所有小写字母,A-z匹配ASCII字符A到ASCII字符z的所有字母。

一定要避免尾字符小于它的首字符,例如[3-1],这种模式没有意义

2.3、取非匹配

表2-3 集合取非元字符
元字符说明转义
^用元字符【^】来表明你想对一个字符集合进行取非匹配

 这与逻辑非运算很相似,只是这里的操作数是字符集合而已。

[ns]a[^0-9]\.xls

[^0-9]匹配任何不是数字的字符,

匹配sam.xls,但 不匹配na1.xls、na2.xls或sa1.xls

sales1.xls
orders3.xls
sales2.xls
sales3.xls
apac1.xls
europe2.xls
sam.xls
na1.xls
na2.xls
sa1.xls
ca1.xls

【^】的效果将作用于给定字符集合里的所有字符或字符区间,而不是仅限于紧跟在^字符后面的那一个字符或字符区间。

三、使用元字符

3.1、对特殊字符进行转义

元字符是一些在正则表达式中有着特殊含义的字符,通过转义使元字符为匹配本身

myArray[0]

没有匹配任何结果,因为[和]在正则表达式

里用来定义一个字符集合,而不是[和]本身

var myArray = new Array();
...
if (myArray[0] == 0){
...
}
myArray\[0\]【\[】匹配[,【\]】匹配]var myArray = new Array();
...
if (myArray[0] == 0){
...
}
myArray\[[0-9]\]匹配myArray[0]、myArray[1]...、myArray[9]

任何元字符都可以通过给它加上一个反斜杠字符作为前缀来进行转义

3.2、匹配空白字符

表3-2-1  元字符分类说明
匹配文本的元字符例如【.】
正则表达式的语法要求例如【[】和【]】
表3-2-2 空白元字符
元字符说明
[\b]回退(并删除)一个字符(backspace键)
\f换页符
\n换行符
\r回车符
\t制表符(tab键)
\v垂直制表符
\r\n\r\n匹配两个连续的行尾标签,正是两条记录之间的空白行

"101","Ben","Forta"
"102","Jim","James"

"103","Roberta","Robertson"
"104","Bob","Bobson"

表3-2-3 Windows、Unix和Linux下空白字符差异
操作系统空白字符同时适配兼容
Windows\r\n应该包含一个可选的【\r】和一个必须被匹配的【\n】
Unix或Linux\n

3.3、匹配特定的字符类别

一些常用的字符集合可以用特殊元字符来代替,这些元字符匹配是某一类别的字符

匹配数字(与非数字)

表3-3-1 数字元字符
元字符说明等同于
\d任何一个数字字符[0-9]
\D任何一个非数字字符[^0-9]
myArray\[\d\]\[匹配[,\d匹配任意单个数字字符,\]匹配]var myArray = new Array();
...
if (myArray[0] == 0){
...
}

匹配字母和数字(与非字母和数字) 

表3-3-2  字母和数字元字符
元字符说明等同于
\w任何一个字母数字字符(大小写均可)或下划线字符[a-zA-Z0-9_]
\W任何一个非字母数字或下划线字符[^a-zA-Z0-9_]
\w\d\w\d\w\d匹配交替出现的\w和\d11213
A1C2E3
48075
48237
M1B4F2
90046
H1H2H2

匹配空白字符(与非空白字符)

表3-3-3 空白字符元字符
元字符说明等同于
\s任何一个空白字符[\f\n\r\t\v]
\S任何一个非空白字符[^\f\n\r\t\v]

用来匹配退格字符的【\b】元字符是一个特例

匹配十六进制或八进制

表3-3-4 十六进制或八进制
前缀说明样例
\x十六进制数值要用前缀\x给出\x0A对应于ASCII字符10(换行符)
\0八进制数值要用前缀\0来给出\011对应于ASCII字符9,等价于\t
\c指定各种控制字符,部分正则表达式支持\cZ将匹配Ctrl-Z

3.4、使用POSIX字符类

POSIX字符类是需要(但不是所有)正则表达式实现都支持的一种简写形式

JavaScript不支持在正则表达式中使用POSIX字符类

表3-4-1 POSIX字符类
字符类说明等价于
[:alnum:]任何一个字母或数字[a-zA-Z0-9]
[:alpha:]任何一个字母[a-zA-Z]
[:blank:]空格或制表符[\t ],t之后还有一个空格
[:cntrl:]ASCII控制字符(0-31,以及127)
[:digit:]任何一个数字[0-9]
[:graph:]和[:print:]一样,但不包括空格

[:lower:]

任何一个小写字母[a-z]
[:print:]任何一个可打印字符
[:punct:]既不属于[:alnum:]也不属于[:cntrl:]的任何一个字符
[:space:]任何一个空白字符,包括空格[^\f\n\r\t\v ],v之后有一个空格
[:upper:]任何一个大写字母[A-Z]
[:xdigit:]任何一个十六进制数字[a-fA-F0-9]
#[[:xdigit]][[:xdigit]][[:xdigit]][[:xdigit]][[:xdigit]][[:xdigit]]匹配六个十六进制<BODY BGCOLOR="#336633" TEXT="#FFFFFF" MAFRINWIDTH="0" ...>

使用的模式以【[[】开头、以【]]】结束,这是POSIX字符所必须的

四、重复匹配

4.1、有多少个匹配

表4-1-1 匹配字符个数元字符
元字符说明转义
+匹配一个或多个(至少一个;不匹配零个字符的情况)等同于{1,}\+
*匹配零次或多次,等同于{0,}\*
?匹配零次或一次,等同于{0,1}\?
{num}匹配指定num次\{或\}
{num1, num2}匹配最少num1次,最多num2次\{或\}
{num1,}最少匹配num1次
\w+@\w+\.\w+\w+匹配一个或多个字符,但不包含多余.的处理,例如ben.forta@forta.com是合理的邮箱地址Send personal email to ben@forta.com, ben.forta@forta.com, ben@urgent.forta.co...
[\w.]+@[\w.]+\.\w+能正常匹配ben.forta@forta.comben@urgent.forta.co等类型的地址Send personal email to ben@forta.com, ben.forta@forta.com, ben@urgent.forta.co...
#[[:xdigit]]{6}匹配六个十六进制<BODY BGCOLOR="#336633" TEXT="#FFFFFF" MAFRINWIDTH="0" ...>
\d{1,2}[-\/]\d{1,2}[-\/]\d{2,4}

匹配形如dd-MM-yy[yy]或dd/MM/yy[yy]的日期格式

最后必须是2到4为的年份,所以2/2/2未匹配

4/8/03
10-6-2004

2/2/2
01-01-01
\d+:\$\d{3,}\.\d{2}最少匹配三位整数以上的记录1001:$496.80
1002:$1290.96

1003:$26.43
1004:$613.90
1005:$7.61
1006:$414.90
1007:$25.00

4.2、防止过度匹配

?、{n}、{m, n}都有重复次数的上限,其他的重复匹配语法在重复次数方面都没有上限值,有时会导致过度匹配的现象。

表4-2-1 常用的贪婪性元字符和他们的懒惰性版本
贪婪性元字符懒惰性元字符说明
**?
++?
{n, }{n, }?
<[Bb]>.*</[Bb]>只找到一个匹配,而不是预期中的两个This offer is not available to customers living in <B>AK</B> and <B>HI</B>.
<[Bb]>.*?</[Bb]>找到两个匹配This offer is not available to customers living in <B>AK</B> and <B>HI</B>.

当惰性元字符后出现复数匹配项时,会选择距离最近的一个匹配项

五、位置匹配

cat所有的cat都匹配了,没区别cat所在位置The cat scattered his food all over the room.

5.1、单词边界限定符

表5-1-1 单词边界限定符
元字符说明备注
\b单词边界,匹配一个单词的开始或结尾b是boundary(边界)的首字母
\B非单词边界,必须不为一个单词的开始或结束
\bcat\b匹配前后都是单词边界的catThe cat scattered his food all over the room.
\Bcat\B匹配在单词里面的catThe cat scattered his food all over the room.

\b匹配的是一个这样的位置,这个位置位于一个能够用来构成单次的字符(字母、数字和下划线,也就是\w相匹配的字符) 

 5.2、字符串边界限定符

表5-2-1 字符串边界限定符
元字符说明备注
^用来定义字符串的开头

位于[]中并紧跟[才被用于求非操作

位于一个字符集的外面并位于一个模式的开头,^将匹配字符串的开头

$用来定义字符串的结尾
<\?xml.*?>任何位置都会被匹配到<?xml version="1.0" ?>
<BODY>xxx</BODY>
This is bad, real bad!
<?xml version="1.0" ?>
<BODY>xxx</BODY>
^\s*<\?xml.*?>仅开头以任意个空格开头的会被匹配<?xml version="1.0" ?>
<BODY>xxx</BODY>
This is bad, real bad!
<?xml version="1.0" ?>
<BODY>xxx</BODY>

 六、使用子表达式

&nbsp;{2,}期望匹配重复2次以上出现的&nbsp;,但实际未匹配,能匹配&nbsp;;...Windows&nbsp;&nbsp;2000...

6.1、子表达式

表6-1-1 子表达式元字符
元字符说明备注
()

子表达式是一个更大的表达式的一部分;

把一个表达式划分为一些列子表的目的是为了把那些子表达式当做一个独立元素来使用

要匹配本身,必须使用\(和\)机型转义
(&nbsp;){2,}将&nbsp;当做一个整体...Windows&nbsp;&nbsp;2000...
\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}上下效果相同Ping hog.forta.com [12.159.46.200] with 32 bytes of data:
(\d{1,3}\.){3}\d{1,3}

提高可读性,各个子表达式都加上括号,例如(\d{1,3}\.){3}(\d{1,3})

6.2、子表达式的嵌套

子表达式允许多重嵌套,理论上没有限制,但应该遵循适可而止的原则

(((\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]))见下方备注Ping hog.forta.com [12.159.46.200] with 32 bytes of data:

此处的示例,实际匹配结果为12.159.46.20,优先满足了\d{1,2}的匹配条件,将(2[0-4]\d)放到四个或判断的最前,可以调整优先级,但是此处案例作用是展示子表达式嵌套,改动必要性不大

((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))分别匹配:

  • 一位或两位数字
  • 1开头的3位数字
  • 2开头的200-249的数字
  • 25开头的250-255的数字

 七、回溯引用:前后一致匹配

<[hH]1>.*</[hH]1>仅能匹配H1标签

<H1>xx</H1>

yy

<H2>xx</H2>

<[hH][1-6]>.*</[hH][1-6]>贪婪匹配,全部被匹配

<H1>xx</H1>

yy

<H2>xx</H3>

<[hH][1-6]>.*?</[hH][1-6]><H2></H3>错误标签被匹配

<H1>xx</H1>

yy

<H2>xx</H3>

7.1、回溯引用匹配

[ ]+(\w+)[ ]+\1匹配连续出现的单词,前后用一个或多个空格隔开This is a block of of text, serveral words here are repeated, and and the should not be.
<[hH]([1-6])>.*?</[hH]\1>前面匹配数字几,\1就匹配几

<H1>xx</H1>

yy

<H2>xx</H3>

[ ]+匹配一个或多个空格

\w+在括号里面是一个子表达式

\1是一个回溯引用,它引用的正是前面划分出来的子表达式;当\w+匹配of时,\1匹配of

 \1代表模式里的第一个子表达式,\2代表模式里的第二个子表达式...

 需要实现里面\0可以用来匹配整个表达式

7.2、回溯引用在替换操作中的应用

搜索模式替换模式匹配文本替换结果
(\w+[\w\.]*@[\w\.]+\.\w+)<a href="mailto:$1">$1</a>ben@forta.com is my email.<a href="mailto:ben@forta.com">ben@forta.com</a> is my email
(\d{3})(-)(\d{3})(-)(\d{4})($1) $3-$5

313-55-1234

248-555-9999

(313) 555-1234

(248) 555-9999

回溯引用语法在不同的正则表达式实现里有很大差异,JavaScript需要用$来替代\;ColdFusion用户在查找和替换操作里都必须使用\。

表7-2-1 用来进行大小写替换的元字符
元字符说明
\E结束\L或\U转换
\l把下一个字符转换为小写
\L把\L到\E之间的字符全部转换为小写
\u把笑一个字符转换为大写
\U把\U到\E之间的字符全部转换为大写
搜索模式替换模式匹配文本替换结果
(<[Hh]1>)(.*?)(</[Hh]1>)$1\U$2\E$3

<H1>xx</H1>

xxx

<H2>xx</H2>

<H1>XX</H1>

xxx

<H2>xx</H2>

八、前后查找

<TITLE>.*</TITLE>期望匹配xml标签内容,不包含标签,但实际包含标签<HEAD><TITLE>xxx</TITLE></HEAD>

8.1、向前查找

向前查找指定了一个必须匹配但不再结果中返回的模式。向前查找实际就是一个子表达式。

表8-1 向前查找元字符
元字符说明备注
?=以?=开头的子表达式,需要匹配的文本跟在=的后面被匹配的文本不包含在最终返回的匹配结果里,这里称为“不消费”
.+(:)匹配任意尽更:的字符,包含冒号

http://www.forta.com

https://mail.forta.com

ftp://ftp.forta.com

.+(?=:)匹配任意紧跟:的字符,不包含冒号:

http://www.forta.com

https://mail.forta.com

ftp://ftp.forta.com

  1. 向前查找(和向后查找)匹配本身其实是有返回结果的,只是这个结果的字节长度永远是0而已。因此前后查找操作有时也被称为零宽度匹配操作。
  2. 任何一个子表达式都可以转换为一个向前查找表达式,只要给它加上一个?=前缀即可

 8.2、向后查找

向后查找就是查找出现在被匹配文本之前的字符(但不消费它)

表8-2 向后查找元字符
元字符说明备注
?<=以?<=开头的子表达式,需要匹配的文本跟在=的后面被匹配的文本不包含在最终返回的匹配结果里,这里称为“不消费”
\$[0=9.]+包含$标识书数字

ABC01: $23.45

HGG42: $5.31

total: 2

[0=9.]+仅标识书数字,但包含了 统计数据,不符合预期

ABC01: $23.45

HGG42: $5.31

total: 2

(?<=\$)[0-9.]+向后查找以$开头的数字,但不包含$

ABC01: $23.45

HGG42: $5.31

total: 2

向前查找模式的长度是可变的,它们可以包含.和+之类的元字符,所以非常灵活;

而向后查找模式只能固定长度,这是一条几乎所有正则表达式实现都遵守的限制。

8.3、把向前查找和向后查找结合起来

(?<=<TITLE>).*(?=</TITLE>)匹配TITLE标签内容,但不包含标签,符合预期<HEAD><TITLE>xxx</TITLE></HEAD>

提示:为减少歧义,应该对需要匹配的<做一下转义,(?<=<改为(?<=\<

8.4、对前后查找取非

向前查找和向后查找通常用来匹配文本,骑目的是为了确定将被返回为匹配结果的文本的位置,这种用法被称为正向前查找(positive lookahead)和正向后查找(positive lookbehind)。

 负向前查找(negative lookahead)将向前查找不与给定模式相匹配的文本,负向后查找(negative lookbehind)将向后查找不与给定模式相匹配的文本。

表8-4 各种前后查找操作符
操作符说明
(?=)正向前查找
(?!)负向前查找
(?<=)正向后查找
(?<!)负向后查找
(?<=\$)\d+向后查找带$的整数I paid $30 for 100 apples.
(?<!\$)\d+向后查找不带$的整数,但第一个0被命中I paid $30 for 100 apples.
\b(?<!\$)\d+不带$的整数但必须前面是空格I paid $30 for 100 apples.

九、嵌入条件

\(?\d{3}\(?-?\d{3}-\d{4}

首字符匹配左括号,则后面匹配右括号了;否则匹配-号

理论不应该匹配(123)-456-7890、(123-456-7890这两条记录

123-456-7890

(123)456-7890

(123)-456-7890

(123-456-7890

1234567890

123 456 7890

需要使用条件处理,并非所有的正则表达式实现都支持条件处理

9.1、正则表达式的条件

正则表达式里的条件要用?来定义

?匹配前一个字符或表达式,如果它存在的话

?=和?<=匹配前面或后面的文本 ,如果它存在的话

回溯引用条件

表9-1 回溯引用条件格式解读
格式解读
(?(backreference)true-regex)

括号里的backreference是一个回溯引用,

true-regex是一个只在backreference存在时才会被执行的子表达式

false-regex是一个只在backreference不存在时才会被执行的子表达式

(?(backreference)true-regex|false-regex)

(<[Aa]\s+[^>]+>\s*>)?

<[Ii][Mm][Gg]\s+[^>]+>

(?(1)\s*</[Aa]>)

<[Aa]\s+[^>]+>\s*>将匹配一个<a>或<A>标签,可有可无

<[Ii][Mm][Gg]\s+[^>]+>将匹配一个<IMG>及其任意属性

(?(1)\s*</[Aa]>)是一个回溯引用条件

?(1)含义:如果第一个回溯引用存在,

本例为<a>标签存在则使用\s*</[Aa]>进行匹配

<TD>

<A HREF="/home"><IMG src="/images/home.gif"></A>

<IMG src="/images/space.gif">

<A HREF="/help"><IMG src="/images/help.gif"></A>

</TD>

(\()?\d{3}(?(1)\)|-)\d{3}-\d{4}(?(1)\)|-)如果(\()?匹配成功则使用\),否则使用-

123-456-7890

(123)456-7890

(123)-456-7890

(123-456-7890

1234567890

123 456 7890

回溯引用编号不需要被转义,因此?(1)是正确的,?(\1)不正确(但后者通常也能工作) 

前后查找条件

\d{5}(-\d{4})?

\d{5}匹配前5个数字

-\d{4}匹配一个连字符和后4个数字,可能出现

11111

22222

33333-

44444-4444

\d{5}(?(?=-)-\d{4})

\d{5}匹配前5个数字

(?(?=-)-\d{4})使用向前查找条件

条件使用?=-来匹配(但不消费)一个连字符,

11111

22222

33333-

44444-4444

附录

表附录-1 常见元字符一览表
类型元字符说明样例
基本元字符.匹配任意单个字符
|逻辑或操作符(a|b)
[]匹配字符集合中的一个字符[ab]
[^]对字符集和求非[^ab]
-定义一个区间[a-z]
\对下一个字符转义\?
数量元字符*匹配前一个字符(子表达式)的零次或多次重复[a-z]*
*?*的懒惰型版本<a>.*?</a>
+匹配前一个字符(子表达式)的一次或多次重复[a-z]+
+?+的懒惰型版本<a>.+?</a>
?匹配前一个字符(子表达式)的零次或一次重复[a-z]?
{n}匹配前一个字符(子表达式)的n次重复\d{3}
{m,n}匹配前一个字符(子表达式)至少m次且至多n次重复\d{3,5}
{m,}匹配前一个字符(子表达式)m次或更多次重复\d{3,}
{m,}?{m,}的懒惰型版本\d{3,}?
位置元字符^匹配字符串的开头
\A匹配字符串的开头
$匹配字符串的结束
\z匹配字符串的结束

\

匹配单词的开头
\>匹配单词的结束
\b匹配单词边界(开头和结束)
\B\b的反义
特殊元字符[\b]退格字符
\c匹配一个控制字符
\d匹配任意数字字符
\D\d的反义
\f换页符
\n换行符
\r回车符
\s匹配一个空白字符
\S\s的反义
\t制表符(TAB字符)
\v垂直制表符
\w匹配任意 字母数字字符或下划线字符

\W

\w的反义
\x匹配一个十六进制数字
\e匹配一个八进制数字
回溯引用和前后查找()定义一个字表达式
\1匹配第1个子表达式;\2代表第2个子表达式,以此类推
?=向前查找
?向后查找
?!负向前查找
?!=负向后查找
?()条件(if then)
?()|条件(if then else)
大小写转换\E结束\L或\U转换
\l把下一个字符转换为小写
\L把后面的字符转换为小写,直到遇到\E为止
\u把下一个字符转换为大写
\U把后面的字符转换为大写,直到遇到\E为止
匹配模式(?m)分行匹配模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

唐毓俊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值