一个正则表达式是一个特定的格式化模式
可以用来找出一个字符串在另一个字符串中的使用情况
几个编程语言
包括Visual Basic
Perl
JavaScript和PHP都支持正则表达式
希望在这篇入门指导的结束
Mitchell(作者自己)可以让你在PHP程序中能应用一些基本的正则表达式
正则表达式是在各种各样的程序语言中突出的古怪特征中的一种
但是由于它们看起来是很难的一个概念
所以很多开发者就把它们放到了角落里
忘记了它们的存在
让我们先来看看什么是正则表达式为什么你要在PHP程序中用到它们
一什么是正则表达式?
你对从一个不错的老的基于控制的文本编辑器中分离出像BBEdit和notepad的程序有什么看法呢?两个都支持文本输入可以让你保存文本到文件中但是现在的文本编辑器也支持其它功能包括查找–代替工具这让编辑一个文本文件相当容易
正则表达式也是相似的只是更好一些正则表达式可以被认为是一个极其高级的查找替换工具让我们从痛苦中摆脱出来不必再写定制的数据确认例子来检查电子邮件地址或者来确认电话号码的格式是正确的如此等等
任何程序中最普通的函数之一就是数据有效性检查PHP捆绑了一些文本检查函数允许我们用正则表达式匹配一个字符串确认有一个空格有一个问号等等
你不知道的可能是正则表达式可以简单装备吗当你掌握了一些正则表达式时(这个正则表达式可以用来告诉正则表达式引擎一个字符串中我们想要匹配的部分)你会自问为什么会把正则表达式扔到角落里这么久^_^
PHP有两套函数用来处理两种类型的正则表达式:Perl兼容模式和Posix标准兼容模式
在这篇文章中我们将看看ereg函数用遵照Posix标准的搜索表达式工作虽然它们并没有Perl模式那样强大但是一种不错的学习正则表达式的方法如果你对PHP支持的Perl兼容正则表达式感兴趣可以到PHPnet网站找一些关于preg函数的细节
PHP有六个函数来处理正则表达式它们都把一个正则表达式作为它们的第一个参数列出如下
ereg: 最常用的正则表达式函数 ereg 允许我们搜索跟一个正则表达式匹配的一个字符串
ereg_replace: 允许我们搜索跟正则表达式匹配的一个字符串并用新的字符串代替所有这个表达式出现的地方
eregi: 和ereg几乎是一样效果不过忽略大小写
eregi_replace: 和ereg_replace有着一样的搜索替换功能不过忽略大小写
split: 允许我们搜索和正则表达式匹配的字符串并且以字符串集合的方式返回匹配结果
spliti: split函数忽略大小写的版本
二为什么使用正则表达式?
如果你不断地建立不同的函数来检查或者操作字符串的一部分现在你可能要放弃所有的这些函数取而代之的用正则表达式如果你对下列的问题都答是的那么你肯定要考虑使用正则表达式了
你是否正在写一些定制的函数来检查表单数据(比如在电子信箱地址中的一个@一个点)? 你是否写一些定制的函数在一个字符串中循环每个字符如果这个字符匹配了一个特定特征(比如它是大写的或者它是一个空格)那么就替换它?除了是令人不舒服的字符串检查和操作方法如果没有有效率地写代码上述的两条也会使你的程序慢下来你是否更倾向于用下面的代码检查一个电子信箱地址呢:
<?php
function validateEmail($email)
{
$hasAtSymbol = strpos($email @);
$hasDot = strpos($email );
if($hasAtSymbol && $hasDot)
return true;
else
return false;
}
echo validateEmail(mitchell@devarticlescom);
?>
或者使用下面的代码:
<?php
function validateEmail($email)
{
return ereg(^[azAZ]+@[azAZ]+\[azAZ]+$ $email);
}
echo validateEmail(mitchell@devarticlescom);
?>
可以肯定的是第一个函数比较容易而且看起来结构也不错但是如果我们用上面的下一个版本的email地址检查函数不是更容易吗?
上面展示的第二个函数只用了正则表达式包括了对ereg函数的一个调用Ereg 函数返回true或者false来声明它的字符串参数是否和正则表达式相匹配
很多编程者避开正则表达式只因为它们(在一些情况下)比其它的文本处理方法更慢正则表达式可能慢的原因是因为它们涉及把字符串在内存中拷贝和粘贴因为正则表达式的每一个新的部分都对应匹配一个字符串但是从我对正则表达式的经验来说除非你在文本中几百个行运行一个复杂的正则表达式否则性能上的缺陷都可以忽略不计当把正则表达式作为输入数据检查工具时也很少出现这种情况
三正则表达式语法
在你可以匹配一个字符串到正则表达式之前你必须先建立正则表达式开始的时候正则表达式的语法有点古怪表达式中的每一个短语代表某个类型的搜索特征下列是一些最普通的正则表达式也都对应着一个如何使用它的例子:
1字符串头部
搜索一个字符串的头部用^例如
<?php echo ereg(^hello hello world!); ?>
将返回 true 但是
<?php echo ereg(^hello i say hello world); ?>
将返回 false 因为hello不在字符串I say hello world的头部
2字符串尾部
搜索字符串尾部用$例如
<?php echo ereg(bye$ goodbye); ?>
将返回true 但是
<?php echo ereg(bye$ goodbye my friend); ?>
将返回 false因为bye不在字符串goodbye my friend的尾部
3任意的单个字符
搜索任意字符用点()例如
<?php echo ereg( cat); ?>
将返回true但是
<?php echo ereg( ); ?>
将返回false因为我们的要搜索字符串没有包含字符你可以用花括号随意告诉正则表达式引擎它要匹配多少个单个字符
如果我只想匹配个字符我可以这样用ereg:
<?php echo ereg({}$ ); ?>
上面的这段代码告诉正则表达式引擎当且仅当至少个连续的字符出现字符串的尾部时返回true我们也可以限制连续出现的字符的数目
<?php echo ereg(a{}$ aaa); ?>
在上面的例子里我们已经告诉正则表达式引擎我们的搜索字符串来匹配表达式它在尾部必须有介于和个的a字符
<?php echo ereg(a{}$ aaab); ?>
上面的例子将不会返回true虽然有三个a字符在搜索字符串里但是它们不是在字符串的尾部如果我们把结尾字符串匹配$从正则表达式中去掉那么这个字符串是匹配的
我们也可以告诉正则表达式引擎来匹配至少有确定数目的字符在一行如果它们存在的可以匹配更多 我们可以这样做
<?php echo ereg(a{}$ aaaa); ?>
4零或多次重复字符
为了告诉正则表达式引擎一个字符可能存在也可以重复我们用*字符这里的两个例子都将返回true
<?php echo ereg(t* tom); ?>
<?php echo ereg(t* fom); ?>
即使第二个例子不包含t这个字符但仍旧返回ture因为*表示字符可以出现但不是必须出现事实上任何普通的字符串模式都会使上面的ereg调用返回true因为t字符是可选的
5一或多次重复字符
为了告诉正则表达式引擎一个字符必须存在也可以重复不止一次我们用+字符像<?php echo ereg(z+ i like the zoo); ?>
下面的例子也会返回true:
<?php echo ereg(z+ i like the zzzzzzoo!); ?>
6零或一次重复字符
我们也可以告诉正则表达式引擎一个字符必须是或者只存在一次或者没有我们用?字符来做这项工作就像
<?php echo ereg(c? cats are fuzzy); ?>
如果我们愿意我们完全可以从上面的搜索字符串中删除c这个表达式会仍旧返回true? 的意思是一个c可以出现在搜索字符串的任何地方但不是必须的
7空格字符
为了匹配一个搜索字符串中的空格字符我们用预定义Posix的类[[:space]]方括号标明连续字符的相关性:space:是实际要匹配的类(在这种情形下是任何空白字符)空白包括tab字符新行字符空白字符或者如果搜索字符串必须包含只有一个空格而不是一个tab或者新行字符你可以用一个空格字符( )在大多数情况下我倾向于使用:space:因为这意味着我的意图不仅仅是单个空格字符这点很容易被忽视这里有一些Posix标准预定义类有一些我们可以作为正则表达式的部分一些Posix标准预定义类包括[:alnum:] [:digit:] [:lower:]等等
我们可以像这样匹配单个空白字符
<?php echo ereg(Mitchell[[:space:]]Harper Mitchell Harper); ?>
我们也可以通过在表达式后用?字符来告诉正则表达式引擎匹配没有空白或者一个空白
<?php echo ereg(Mitchell[[:space:]]?Harper MitchellHarper); ?>
8模式分组
相关的模式可以在方括号里分在一起很容易用[az]和[AZ]指定只有一个小写字母或者一列大写字母以搜索字符串的一部分存在
<?php
// 要求从第一个到最后一个都是小写字母
echo ereg(^[az]+$ johndoe); // 返回true
?>
或者像
<?php
// 要求从第一个到最后一个都是大写字母
ereg(^[AZ]+$ JOHNDOE); // 返回 true?
?>
我们也可以告诉正则表达式引擎我们希望或者是小写字母或者是大写字母我们只要把[az]和[AZ]模式结合在一起就可以做到
<?php echo ereg(^[azAZ]+$ JohnDoe); ?>
在上面的例子里如果我们能匹配John Doe而不是JohnDoe将是非常有意义的我们用下面的正则表达式来做这个
^[azAZ]+[[:space:]]{}[azAZ]+$
很容易搜索一个数字字符串
<?php echo ereg(^[]+$ ); ?>
9词语分组
不仅仅搜索模式可以分组我们也可以用圆括号把相关的搜索词语进行分组
<?php echo ereg(^(John|Jane)+$ John Doe); ?>
在上面的例子中我们有一个字符串头部字符紧跟着John或者Jane至少有一个其它字符然后一个字符串尾部字符所以…
<?php echo ereg(^(John|Jane)+$ Jane Doe); ?>
将也匹配我们的搜索模式
10特殊字符的情形
因为一些字符要用在一个搜索模式的明确分组或者语法上像在(John|Jane)中的圆括号我们需要告诉正则表达式引擎来屏蔽这些字符加工它们使之成为被搜索字符串的一部分而不是搜索表达式的一部分我们所用的方法称为字符转义涉及到将任何专用符号加上反斜槓所以例如如果我想在我的搜索中包含|那么我就可以这样做
<?php echo ereg(^[azAz]+\|[azAz]+$ John|Jane); ?>
这里只是少量的一些你要转义的字符你必须转义^ $ ( ) [ | * ? + \ and {
四正则表达式例子
希望你现在对正则表达式实际上有多么强大有了一点点感觉了现在让我们看两个用正则表达式来检查数据中一个字符串的例子
例子一
让我们把第一个例子做的相当简单检验一个标准的URL一个标准的URL(没有端口号)有三个部分构成
[协议]://[域名]
让我们从匹配URL的协议部分开始并且让它只能用http或者ftp我们可以用下面的正则表达式做到这点
^(http|ftp)
^字符特指字符串的头部利用圆括号把http和ftp围住且用或者符号(|)将它们分开我们告诉正则表达式引擎http和ftp两者之一必须在字符串的开头
一个域名通常由wwwsomesitecom构成但是可以随意选择要不要www部分为了例子简单我们只允许comnet和org的域名是在考虑之中的我们最好这样对正则表达式中的域名部分表示如下
(www\)?+\(com|net|org)$
把所有的东西放在一起我们的正则表达式就可以用作检查一个域名如
<?php
function isValidDomain($domainName)
{
return ereg(^(http|ftp)://(www\)?+\(com|net|org)$ $domainName);
}
//真(true)
echo isValidDomain(http://wwwsomesitecom);
//真(true)
echo isValidDomain(ftp://somesitecom);
//假 (false)
echo isValidDomain(ftp://wwwsomesitefr);
//假 (false)
echo isValidDomain(wwwsomesitecom);
?>
例子二
因为我居住在澳大利亚悉尼让我们检查一个典型的澳大利亚国际电话号码澳大利亚国际电话号码的格式如下
+x xxxxxxxx
第一个x是区号其它的都是电话号码检查以+开头且紧跟一个在到之间的区号的电话号码我们用下面的正则表达式
^\+[][[:space:]]
注意上面的搜索模式把+字符用\转义以便于可以在搜索中包含不至于被解释为一个正则表达式[]告诉正则表达式引擎我们需要包含一个到之间的数字[[:space:]]类则告诉正则表达式期望在这里有一个空白
这里是电话号码剩下的搜索模式
[]{}[]{}$
这里没有什么不寻常的地方我们只是告诉正则表达式引擎电话号码可用的数字它必须是个数字的组合跟着一个连接符再跟着另一个个数字的组合然后一个字符串尾部字符
把完整的正则表达式放在一起放进一个函数我们可以用代码来检查一些澳大利亚国际电话号码
<?php
function isValidPhone($phoneNum)
{
echo ereg(^\+[][[:space:]][]{}[]{}$ $phoneNum);
}
// 真(true)
echo isValidPhone(+ );
// 假(false)
echo isValidPhone(+ );
//假( false)
echo isValidPhone(+ );
?>
五总结
正则表达式用一些不适合书写和重复的代码来检查一个字符串我们已经讲解了所有的Posix标准正则表达式的基础包括字符分组和PHP ereg函数我们也知道了怎么用正则表达式来检查一些PHP中简单的字符串
译者注释本人英文不怎么好可能一些地方有出入本文中的字符类其实是我们所说的字符簇