正则表达式学习笔记

起源

首先美国两位神经生理方面的科学家,研究出一种用数学方式来描述神经网络的新方法,他们创新的将神经系统中的神经元描述为小而简单的自动控制元,从而做出一种伟大的工作革新。后来,数学科学家在他们工作的基础上发表了一篇论文,题目是《神经网事件的表示法》,书中利用正则集合的数学符号描述此类模型,引入了正则表达式的概念。

PHP中的正则函数

首先要澄清一些概念:虽然不同语言间正则语法大同小异,但实际上正则表达式的实现有多种引擎,其表现又有多种风格(如JavaScript中有自己的朴素正则,Perl有一套高级而华丽的正则,.NET也有自己的正则风格)。另外,还有人可能容易混淆PHP中的preg和ereg。
简单的说,PHP中有两套正则函数,两者功能差不多:

1.由PCRE库提供的函数,以“preg_”为前缀命名

PCRE(Prel Compatible Regular Expression,兼容Perl的正则表达式)

2.有POSIX扩展提供的函数,以“ereg_”为前缀命名

POSIX是UNIX中的一系列规范构成,其中包含BRE基本型正则表达式和ERE扩展型正则表达式两大流派。

注意:

自PHP5.3以后,就不在推荐使用POSIX这则函数库了,若程序中使用了就会报Deprecated级别的错误。

正则表达式的组成

在PHP里,一个正则表达式分为三个部分:分隔符、表达式和修饰符。
分隔符:可以是除了字母、数字、反斜杠(\)及空白字符以外的任何字符。为了避免混淆,一般不使用正斜线作为分隔符。
表达式:由一些特殊字符和非字符的字符串组成。
修饰符:用于开启或者关闭某种功能/模式。

测试工具

Regex Tester
Fierfox扩展:Regular Expression Tester

元字符

定义

元字符是正则表达式中具有特殊意义的专用字符,用来规定其前导字符(即位于元字符前面的字符)在目标对象中的出现模式。

常见元字符

常见元字符有很多种,如:。。。

.

匹配除换行符以外的任意字符

\w

匹配字符或数字或下划线或汉字

\s

匹配任意空白字符

\d

匹配数字

\b

匹配单词的开始或结束,
也就是单词的分解处,虽然通常英文单词是由空格、标点符号或者换行符来分割,但是“\b”并不是匹配这些单词分割字符中的任何一个,它只是一个位置

^

匹配字符串的开始

$

匹配字符串的结束

-

表示范围,可以与下一个元字符组合使用,如[0-9] 与\d同义、[a-z0-9A-Z_] 与\w同义

[ ]

匹配括号中的任意一个字符,注意是匹配其中的单个字符,比如 b[abc] 可以匹配ba、bb、bc,而babc则不匹配。

*、+、?

量词
* 重复0次或者更多次
+ 重复1次或者更多次
? 重复0次或者1次
{n} 重复n次
{n,} 重复n次或者更多次
{n,m} 重复n到m次

匹配规则

如果想要匹配没有预定义元字符的字符集合,或者表达式与已知定义相反,或者存在多种匹配情况,就需要使用匹配规则了。

字符组

如 [0-9a-zA-Z_] 一个字符组
字符组很简单,但是一定要弄清楚字符组中什么时候需要转义。

转义

如果想查找或匹配元字符本身,比如查找*、?等就会出现问题:没办法指定,因为它们会被解释成别的意思。这时就使用 \ 来取消这些字符的特殊意义。因此,应该使用 \. 和 \* 。当然查找 \ 本身用 \\ 。这就叫做转义。
在PHP里使用反斜杠 \ 表示转义, \Q 和 \E 也可以再模式中忽略正则表达式元字符,比如:\d+\Q.&.\E& ,这个表达式先匹配一个或多个数字,紧接着一个点号,然后一个$,在然后一个点号,最后是字符串结尾。也就是说,\Q 和 \E 之间的元字符都会被作为普通字符用来匹配。 【注意:\Q\E是在PHP中生效】
由于字符组 [ ] 匹配的里面的单个字符,所以他里面的内容不需要转义。例如:c[aou?*]t  是合法的,当然如果转义了也是无效的,不过 \ 就不能再匹配了,例如:[abc\}] 中的 \ 就不能再匹配了。

反义

有些时候,查找的字符不是某个字符类,或者表达式和已知定义相反(比如除了数字以外的任意字符),这时就需要用到反义。反义有一个比较明显的特征:和已知的元字符相反,并且都为大写。在日常工作中反义用的不多,因为反义扩大了范围,而可能造成自己没有考虑到的情况。常用的反义有:

\W

匹配任意不是字母、数字、下划线、汉字的字符

\S

匹配任意不是空白符的字符

\D

匹配任意非数字的字符

\B

匹配不是单词开头或者结束的位置

[^x]

匹配除了x以外的任意字符。【注意:这里的^是“非”的意思,和前面的^不一样】

[^aeiou]

匹配除了aeiou这几个字母以外的字符

分支

分支就是存在多种可能的匹配情况。例如要匹配“cat”、“hat”、“toat”,用字符组[chto]at就不能匹配,这时候就要用到分支了。
对于上面的例子,使用分支的匹配可以这么做:(c|h|to)at,其中括号里的表达式将视作一个整体(括号以上一种元字符,在分组的概念里面会讲到), | 表示分支,即可能存在的多种情况,可以匹配多个字符。相对字符组而言,分支的功能更强大,字符组只能对单个字符“分支”,而分支可以是多个字符以及更复杂的表达式。但对于单个字符,字符组的方式更加高效,所以说能用字符组的时候不要使用分支。
正则表达式分支条件指有几种规则,无论满足哪一种规则都能匹配。例如:0\d{2}-\d{8}$|\0\d{3}-\d{4}$   或者\(0\d{2}\)[-]?\d{8}|0\d{2}[-]?\d{8} 可以匹配类似于022-88889999等

分组

重复单个字符只需要直接在字符后面加上限定符,但如果想重复多个字符又该怎么办呢?可以用小括号指定子表达式,然后规定这个子表达式的重复次数,以可以对子表达式进行其他一些操作。这就是分组。
例如IP地址匹配表达式如下:(\d{1,3}\.){3}\d{1,3},当然了,这个并不能严格匹配IP地址,
要想完整匹配,可以用这样的表达式:(( 2[0-4]\d|25[0-5]| [01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)

常用的分组语法有:

捕获

(exp) 匹配exp,并捕获文本到自动命名的组里
(?<name>exp) 匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp)
(?:exp) 匹配exp,不捕获匹配的文本,也不给此分组分配组号

零宽断言

零宽断言用于查找表达式exp之前或者之后的一个位置,也就是说可以匹配某些之后或者之前是exp的字符串。
(?=exp) 匹配exp前面的位置
(?<=exp) 匹配exp后面的位置
(?!exp) 匹配后面跟的不是exp的位置
(?<!exp) 匹配前面不是exp的位置

注释

(?#comment) 提供注释辅助阅读,不对正则表达式的处理产生任何影响



一些例子

1,匹配以字母a开头的单词: \ba\w*\b
2,匹配1个或者多个连续的数字: \d+
3,匹配刚好6个字符的单词: \b\w{6}\b
4,匹配填写的QQ号必须为5~11位数字: ^\d{5,11}$
5,匹配中国部分地区的电话号码: \d*-\d* 【注意:这里的“-”不是上面的元字符,只匹配它本身(连字符),或者叫减号、中横线等等....】
6,匹配不包含空白符的字符串:\S+
7,用尖括号括起来,以a开头的字符串:<a[^>]+>



惯例与需要注意的地方

*:正则表达式中并没有提供关于数学的任何功能,所以只能使用冗长的分组、选择、字符类来描述!
1,单词:正则表达式里“单词”指不少于1个的连续字母和数字。
2,在学习量词的过程中,要注意*和?这两个量词,在通配符中也有这两个符号,要注意他们之间的区别

注:

本笔记是在阅读《PHP核心技术与最佳实践》中产生的,感谢下原作者哈~很好的一本书。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值