PHP学习笔记之正则表达式

本文详细介绍了PHP中正则表达式的应用,包括字符集、重复、子表达式、定位、分支等核心概念,以及如何使用正则表达式进行查找、替换和分割字符串。

PHP学习笔记之正则表达式

最近开始正式学习PHP,由于刚入门,之前零零散散的在网上搜索,对php正则表达式这一块的内容没有一个系统的认识,所以现在做一下小小的总结,我看的书是《PHP和MySQL Web开发》(原书第四版),很厚一本,趁着寒假读完吧。

一、基础知识

  • 正则表达式是一种描述一段文本模式的方法。

  • 在PHP中,匹配正则表达式有点像 strstr() 匹配,而不像相等比较,因为是在一个字符串的某个位置(如果不指明则可能在字符串中的任何位置)匹配另一个字符串。
    例如,字符串"shop"既可以匹配正则表达式"shop",也可以匹配正则表达式"h","ho"等。

  • 除了精确匹配字符外,还可以用特殊字符来指定表达式的元意。
    例如,使用特殊字符,可以指定一个在字符串开始或末尾肯定存在的模式,该模式的某部分可能被重复,或模式中的字符属于特定的某一类型。此外,还可以按特殊字符的出现来匹配。

二、字符集和类

字符集可以用于匹配属于特定类型的任何字符;事实上是一种通配符。
例如:

 .at

可以与"cat"、“sat”、"mat"进行匹配。(通常这种通配符匹配用于操作系统的文件名匹配)

但上述同样可以匹配‘#at’,如果要限定是az之间的字符,则可以像下面这样指明:

[a-z]at
  • 任何被包含在方括号([ ])中的内容都是一个字符类——一个被匹配字符所属的字符集合。注意,方括号中的表达式只匹配一个字符。例如,
[aeiou]			//表示元音字母
[a-zA-Z]		//表示任何的大小写字母

此外,还可以用集合来指明字符不属于某个集。当把脱字符号 (^) 包括在方括号里面时,表示否。例如,

[^a-z]			//匹配任何不在a到z之间的字符

三、重复

通常,程序员会希望指明某个字符串或字符类将不止一次地出现,在正则表达式中可使用两个特殊字符代替。

  • 符号 * 表示这个模式可以被重复0次或更多次,符号 + 则表示这个模式可以被重复1次或更多次。这两个符号均要放到表达式的后面。例如,
[[a-zA-z]]	+	//表示至少有一个英文字母

四、子表达式

  • 通常,将一个表达式分割为几个子表达式是非常有用的。例如,可以表示“至少这些字符串中的一个需要精确匹配”。可以使用圆括号来实现,与数学表达式中的方法一样。例如,
(very)*large	//可以匹配“large”、“very large”、“very very large”等
  • 除此之外,可以在花括号({ })中的数字表达式来指定内容允许重复的次数。例如,
(very ){1, 3}	//表示重复1~3次,即匹配“very”、“very very”和“very very very”
(very ){3}		//表示重复3次,即匹配“very very very”
(very ){2, }	//表示至少重复2次,即匹配“very very”和“very very very···”及更多。

五、定位到字符串的开始或末尾

  • 脱字符号(^)用于正则表达式的开始,表示子字符串必须出现在被搜索字符的开始处。
  • 字符"$"用于正则表达式的末尾,表示子字符串必须出现在字符串的末尾。
  • 也可以确定一个特定的子表达式是否出现在开始、末尾或在两个位置都出现,当要确定字符串中只有要找的单词而没有其他单词出现时,可以这么使用。
    例如,
^bob		//在字符串开始时匹配bob
com$		//将匹配com出现在字符串末尾处的字符串
^[a-z]$		//匹配只包含a到z之间一个字符的字符串

六、分支

可以使用正则表达式中的一条竖线来表示一个选择。例如,要批评com、edu或net,可以使用如下所使表达式:

com|edu|net

七、匹配特殊字符

如果要匹配前面提到过的特殊字符,如,. 、{ 或 $,就必须在它们前面加一个反斜杠(\)。如果要匹配一个反斜杠,则必须用两个反斜杠(\)来表示。
注:在PHP中,最好将正则表达式模式包括在一个单引号字符串中,使用双引号引用的表达式将带来一些不必要的麻烦。这里为避免混淆,不具体说明,如有兴趣,可自行搜索了解。

下面用表格总结一下特殊字符在方括号内/外的含义:

表1 在POSIX正则表达式中,用于方括号外面的特殊字符摘要

字符意义字符意义
\转义字符)子模式的结束
^在字符串开始匹配*重复0次或更多次
$在字符串末尾匹配+重复1次或更多次
.匹配除换行符(\n)之外的字符{最小/最大量记号的开始
|选择分支的开始(读为或)}最小/最大量记号的结束
(子模式的开始?标记一个子模式为可选的

表2 在POSIX正则表达式中,用于方括号里面的特殊字符摘要

字符意义
\转义字符
^非,仅用在开始位置
-用于指明字符范围

八、正则表达式的应用

  • 第一个用途是查找特定的名词,使用一个正则表达式同时匹配多个字符串。例如,
shop|customer service|retail
  • 第二个用途以匹配电子邮件地址的格式为例,这个格式中包含一些数字或标点,接着是符号@,然后是包括文字或数字和字符串组成的字符串,后面接着是一个“.”(点号),后面包括文字或数字以连字符组成的字符串,还可能有更多的点号,直到字符串结束,它的编码如下所示:
^[a-zA-Z0-9_\-.]+@[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-.]+$

解释如下:
^[a-zA-Z0-9_\-.]+
表示“至少由一个字母、数字、下画线、连字符、点号或者这些字符组合为开始的字符串”。
注意,当在一个字符类的开始或末尾处使用点号时,点号将失去其特殊通配符的意义,只能成为一个点号字符。

@表示匹配字符“@” 

子表达式[a-zA-Z0-9\-]+ 与包含文字数字字符和连字符的主机名匹配。请注意,我们去除了连字符,因为它是方括号内的特殊字符。

字符组合“\.”匹配“.”字符。在字符类外部使用点号,必须对其转义,使其匹配一个点号字符。

子表达式[a-zA-Z0-9\-.]+$ 匹配域名剩下部分,它包含字母、数字和连字符,如果需要还可以包含更多的点号直到字符串的末尾。

九、用正则表达式查找子字符串

用正则表达式查找子字符串,这是正则表达式的主要应用。
在PHP中,可以使用的并且用于匹配POSIX风格正则表达式的两个函数是ereg()和eregi()。( eregi()除了不区分大小写外,其他功能与ereg()一样 )
ereg()函数原型如下:

int ereg(string pattern, string search, array [matches]);

该函数搜索字符串serch,在pattern中寻找与正则表达式相匹配的字符串。如果发现了pattern的子表达式相匹配的字符串,这些字符将会存储在数组matches中,每个数组元素对应一个子表达式。
例如:

if (!eregi( '^[a-zA-Z0-9_\-.]+@[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-.]+$', $email)){
	echo "<p>That is not a valid eamil address.</p>";
	exit;
}

注:PHP中的ereg()函数存在截断漏洞,在CTF比赛中可能会用到,可参考下面这篇文章ereg()截断漏洞

十、用正则表达式替换子字符串

正则表达式也可用来查找和替换子字符串,与此相关的两个函数是ereg_replace()和eregi_replace(),其原型如下所示:

string ereg_replace(string pattern, string replacement, string serch);

该函数在字符串serch中查找正则表达式pattern的字符串,并用字符串replacement来替换。
函数eregi_replace()除了不区分大小写外,其他与ereg_replace()相同。

十一、用正则表达式分割字符串

另一个实用的正则表达式函数是split(),它的原型如下所示:

array split(string pattern, string search[, int max]);

这个函数将字符串search分割成符合正则表达式模式的子字符串,然后将子字符串返回到一个数组中。整数max指定进入数组中的元素个数。
该函数对分割电子邮件地址、域名或日期非常有用,例如,

$address = "username@example.com";
$arr = split ("\.|@ ", $address);
while (list($key, $value) = each($arr)){
	echo "<br>".$value;
}

以上代码将主机名分割成5个部分并将它们分别输出到一行:

username
@
example
.
com
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值