php正则表达式入门教程

Eddy 发布于2012-11-4 10:22:23 分类: 网站相关 已浏览loading 网友评论0条 我要评论

[FONT-SIZE=3]
[FONT-COLOR=Blue]闲时翻译的一篇php正则入门教程,没翻译完。。。[/FONT-COLOR]

一、什么是正则表达式?

    从最基本的方面来理解,正则表达式可以被视为一种字符串的模式匹配或匹配模式。在php中,最常用的是PCRE(Perl Compatible Regular Expressions)库。在这里,我们将努力去让你理解那些毫无意义的象形文字(元字符),让你在自己的应用程序中可以使用这样一个强大的工具。不要想着一口气能吃成一个胖子,一点一滴的学习,当你遇到不同的问题时可以回头再来学习它^_

二、我们从哪里开始呢?

在开始之前,让我们来创建一个字符串:
[CODE=php]// 创建字符串
$string = 'abcdefghijklmnopqrstuvwxyz0123456789';

// 输出字符串
echo $string;

?>[/CODE]
如果我们只是简单的确定模式字符串'abc'是否在我们创建的长字符串($string)中,我们可以这样来做:
[CODE=php]
// 创建字符串
$string = 'abcdefghijklmnopqrstuvwxyz0123456789';

echo preg_match("/abc/", $string);
?>
[/CODE]
上面的代码会输出1。因为对于正则表达式("/abc/")发现了1次匹配,也就是说在长字符串$string中模式字符串'abc'出现了1次。如果没有匹配则preg_match()会返回0。preg_match函数在发现第一次匹配后会停止继续搜索。当然了,在实际的应用中,你不会这样去做,因为在php中有函数(strpos()、strstr())可以更快的实现该功能。

三、匹配字符串的开始

现在我们希望看到一个字符串始于abc。正则表达式中匹配字符开头的元字符为脱字符号^。如果我们想看看字符串是否始于abc,我们可以这样来使用:
[CODE=php]// create a string
$string = 'abcdefghijklmnopqrstuvwxyz0123456789';

// try to match the beginning of the string
if(preg_match("/^abc/", $string))
{
// if it matches we echo this line
echo 'The string begins with abc';
}
else
{
// if no match is found echo this line
echo 'No match found';
}
?>[/CODE]
从上面的代码中,我们看到会输出以下内容:
The string begins with abc
正斜线是正则表达式的分界符,并用双引号包含。因此我们看到,使用元字符^会匹配字符串的开头,而不管它后面是什么字符。

四、如果我想要匹配时区分大小写,该怎么办呢?

如果你使用上面的代码匹配如下模式:
if(preg_match(“/^ABC/ ",$string))
那么该脚本会输出:
No match found
这是由于搜索是大小写敏感的,'abc'和'ABC'是不一样的。如果我们想同时匹配'abc'和'ABC',我们需要使用一个修饰符来使得搜索不区分大小写。php中的正则表达式和大多数正则表达式一样,使用修饰符'i'来表示不区分大小写。现在我们的脚本可能看起来像这样:
[CODE=php]// create a string
$string = 'abcdefghijklmnopqrstuvwxyz0123456789';

// try to match our pattern
if(preg_match("/^ABC/i", $string))
{
// echo this is it matches
echo 'The string begins with abc';
}
else
{
// if not match is found echo this line
echo 'No match found';
}
?>[/CODE]
现在脚本能够匹配到abc,当然也能匹配到abc、ABC、Abc、aBc……。在本教程后面会有更多的修饰符介绍。

五、如何匹配字符串的结尾呢?

匹配字符串结尾和匹配字符串开始的方式大部分都是相同的。一个很多人常犯的错误是用元字符$去匹配字符串结尾,这是不正确的做法,应该用\z来实现。考虑下面这个表达式
[CODE=php]preg_match("/^foo$/", "foo\n")[/CODE]
该表达式会返回1,因为$跟\Z一样。因此不想匹配新行时,就不应该用$。$元字符在有m修饰符的情况下会匹配多次,但\z不会。让我们对上面的代码做点小修改,去掉模式串开头的^并在结尾添加\z,i修饰符将继续保留。
[CODE=php]// create a string
$string = 'abcdefghijklmnopqrstuvwxyz0123456789';

// try to match our pattern at the end of the string
if(preg_match("/89\z/i", $string))
{
// if our pattern matches we echo this
echo 'The string ends with 89';
}
else
{
// if no match is found we echo this line
echo 'No match found';
}
?>[/CODE]
上面的脚本会输出:
The string ends with 89
。到目前为止看上去都很简单^_
[FONT-COLOR=Red]备注:
\Z 字符串结尾或行尾(不受处理多行选项的影响)
\z 字符串结尾(不受处理多行选项的影响)[/FONT-COLOR]

六、元字符

在我们与正则表达式初次接触时我们做了一些简单的模式匹配,同时我们介绍了字符^和$。这些字符有着特殊的含义,就像我们所见到的一样,^匹配字符串开始,$匹配字符串结束。这些字符包括其他一些特殊字符我们称之为元字符,下面列出了php中使用的一些元字符:
[CODE]. (匹配除换行符以外的任意字符)
^ (匹配字符串的开始)
* (量词, 0次或多次匹配)
+ (量词, 1次或多次匹配)
? (作为量词, 表示0次或1次匹配. 位于量词后面用于改变量词的贪婪特性)
{ (自定义量词开始标记)
[ (开始字符类定义)
] (结束字符类定义)
\ (转义字符)
| (开始一个可选分支)
( (子组的开始标记)
) (子组的结束标记)
} (自定义量词结束标记)[/CODE]
我们将在本教程中介绍各个元字符的含义及用法,掌握这些元字符的含义是非常重要的。如果你想搜索一个包含这样字符串的字符串,比如含有'1+1',那么你需要用反斜线\对元字符进行转义:
[CODE=php]
?php
// create a string
$string = '1+1=2';

// try to match our pattern
if(preg_match("/^1\+1/i", $string))
{
// if the pattern matches we echo this
echo 'The string begins with 1+1';
}
else
{
// if no match is found we echo this line
echo 'No match found';
}
?>
[/CODE]
上面这段脚本会输出:
The string begins with 1+1
因为它发现了1+1而忽略了元字符+的特殊含义。如果你不对元字符进行转义而用如下的表达式
[CODE=php]preg_match("/^1+1/i", $string)[/CODE]
匹配将会失败。如果你想匹配\,那你同样要对其进行转义。但是我们同样需要要对控制字符进行转义,因为本身就是反斜线,所以需要进行两次转义:
\\\\

七、其他元字符表示什么含义呢?

我们已经学习了元字符[FONT-COLOR=Red]^[/FONT-COLOR]和[FONT-COLOR=Red]$[/FONT-COLOR]的用法,现在让我们来看看其他元字符。首先要介绍的是[FONT-COLOR=Red][][/FONT-COLOR],用来指定一个字符类。
一个什么?
一个字符类,也就是你想匹配的字符的一个集合,他们可以单独的像下面这样被列出:
[abcdef]
或者用一个范围符号[FONT-COLOR=Red]-[/FONT-COLOR]来表示:
[a-f]
[CODE=php]
// create a string
$string = 'big';

// Search for a match
echo preg_match("/b[aoiu]g/", $string, $matches);

?>
[/CODE]
上面的脚本将会输出1,因为preg_match()函数发现了一处匹配。上面的代码同样会匹配字符串'bag'、'bog'、'big',但是不会匹配字符串'beg'。字符范围集[a-f]与字符集[abcdef]所表示的意思相同,可以把它想象成从a到f。另外,它们是大小写敏感的,所以[A-F]与[a-f]的含义是不同的。
元字符在字符集中是没有特殊含义的,所以你不需要去对它进行转义。例如你有一个如下的字符集:
[abcdef$]
它会匹配字符a、b、c、d、e、f、$,$在字符集里面只是一个简单的$符号,没有特殊的含义。
现在我们已经明白元字符在字符集中时是没有特殊含义的,接下来我们将学习如何在字符集中应用元字符。是的,我说过它没有特殊含义,但那只是在绝大多数情况下,有时候它也会有特殊的含义。
正则表达式的强大之处还在于可以去匹配一个字符集之外的任意字符。实现这个功能我们需要将元字符[FONT-COLOR=Red]^[/FONT-COLOR]放到字符集的开头,放在其他任何地方都只是一个普通的字符[FONT-COLOR=Red]^[/FONT-COLOR],没有特殊含义。现在我们来看看如何去匹配除了字符b之外的任意字符。
[CODE=php]// create a string
$string = 'abcefghijklmnopqrstuvwxyz0123456789';

// echo our string
preg_match("/[^b]/", $string, $matches);

// loop through the matches with foreach
foreach($matches as $key=>$value)
{
echo $key.' -> '.$value;
}
?>[/CODE]
上面的脚本会输出:
0 -> a
发生了什么呢?preg_match()函数发现第一个字符a和模式/[^b]/匹配。让我们对上面的代码做点小改变,用preg_match_all()去匹配字符串$string中的所有字符:
[CODE=php]
// create a string
$string = 'abcefghijklmnopqrstuvwxyz0123456789';

// try to match all characters not within out pattern
preg_match_all("/[^b]/", $string, $matches);

// loop through the matches with foreach
foreach($matches[0] as $value)
{
echo $value;
}
?>
[/CODE]
上面的脚本将会输出字符串中除了字符b之外的所有字符:
acefghijklmnopqrstuvwxyz0123456789
另外,我们还可以用它来过滤掉一个字符串中的数字:
[CODE=php]
// create a string
$string = 'abcefghijklmnopqrstuvwxyz0123456789';

// match any character that is not a number between 0 and 9
preg_match_all("/[^0-9]/", $string, $matches);

// loop through the matches with foreach
foreach($matches[0] as $value)
{
echo $value;
}
?>
[/CODE]
上面的代码发生了什么呢?我们用preg_match_all()函数去匹配我们的模式串,这个模式串用了元字符[FONT-COLOR=Red]^[/FONT-COLOR]和字符集[]去匹配除了0-9之外的所有字符。
因此,你可以简单的记忆元字符[FONT-COLOR=Red]^[/FONT-COLOR]用在字符集中表示的意思是非(NOT)。

八、还要跟着我继续学习吗?

好的,我们继续!我们来看看最常用的元字符:反斜线([FONT-COLOR=Red]\[/FONT-COLOR])
在正则表达式中,反斜线([FONT-COLOR=Red]\[/FONT-COLOR])有几种不同的用法。第一个用法是用来进行转义,反斜线([FONT-COLOR=Red]\[/FONT-COLOR])可以用来转义所有元字符,包括其自身,因此你可以运用模式字符串来匹配它们。如果我们的字符串是这样的
"This is a [templateVar]"
我们想搜索[templateVar],我们可以这样来实现:
[CODE=php]
// create a string
$string = 'This is a [templateVar]';

// try to match our pattern
preg_match_all("/[\[\]]/", $string, $matches);

// loop through the matches with foreach
foreach($matches[0] as $value)
{
echo $value;
}
?>
[/CODE]
上面的脚本会输出结果:
[]
这是因为我们想匹配[]。如果没有反斜线,则模式字符串是这样[FONT-COLOR=Red]"/[[]]/"[/FONT-COLOR],但是我们必须对我们想要搜索的[FONT-COLOR=Red][[/FONT-COLOR]和[FONT-COLOR=Red]][/FONT-COLOR]进行转义。同样,你必须对反斜线也要进行转义。如果你有一个像这样的字符串:
c:\dir\file.php
在模式字符串中你应该用\\。
反斜线还可以被用来表示特殊的字符序列。
接下来要介绍的元字符是点号([FONT-COLOR=Red].[/FONT-COLOR])。
点号可以用来匹配除换行(如\n、\r)之外的任意字符。因此我们可以用它来匹配除换行之外的任意字符。为了可以让点号[FONT-COLOR=Red].[/FONT-COLOR]可以匹配任意字符,包括换行,你可以使用/s修饰符。首先,我们来看看如何使用不带/s的点号[FONT-COLOR=Red].[/FONT-COLOR]来匹配任意字符:
[CODE=php]
// create a string
$string = 'sex at noon taxes';

// look for a match
echo preg_match("/s.x/", $string, $matches);

?>
[/CODE]
可以看到,输出结果为1。这是因为preg_match()函数发现了一处匹配。这个例子同样会匹配sax,six,sox,sux和s x,但是不会匹配stix。
现在我们来看看匹配换行符,在我们的例子中我用[FONT-COLOR=Red]\n[/FONT-COLOR]来表示换行。
[CODE=php]
// create a string
$string = 'sex'."\n".'at'."\n".'noon'."\n".'taxes'."\n";

// echo the string
echo nl2br($string);

// look for a match
echo preg_match_all("/\s/", $string, $matches);

?>
[/CODE]
上面脚本会输出以下结果:
sex
at
noon
taxes
4
首先为了观察到新行,我们输出字符串。然后我们看到最后输出了4.这是因为当我们用\s标志时preg_match_all()函数发现了四处匹配([FONT-COLOR=Red]\n[/FONT-COLOR])。稍后我们将学习更多的特殊字符序列。
接下来我们要学习的元字符是星号字符([FONT-COLOR=Red]*[/FONT-COLOR])。这个元字符匹配在它前面的字符0次或多次,这意味着在它前面的字符可能出现,也可能不出现。因此[FONT-COLOR=Red].*[/FONT-COLOR]将匹配任意数量的任意字符。例如:
[CODE=php] // create a string
$string = 'php';

// look for a match
echo preg_match("/ph*p/", $string, $matches);

?> [/CODE]
我们再一次发现结果为1,因为我们发现了1处匹配。在上面的例子中匹配的是一个h字符,它同样可以匹配pp(0个h字符)、phhhp(3个h字符)。
这一节我们将要讨论加号([FONT-COLOR=Red]+[/FONT-COLOR])元字符。元字符[FONT-COLOR=Red]+[/FONT-COLOR]与[FONT-COLOR=Red]*[/FONT-COLOR]有类似的含义,[FONT-COLOR=Red]+[/FONT-COLOR]匹配1次或多次,而[FONT-COLOR=Red]*[/FONT-COLOR]匹配0次或多次。在前面的例子中我们看到[FONT-COLOR=Red]*[/FONT-COLOR]会匹配字符串'pp',但是元字符[FONT-COLOR=Red]+[/FONT-COLOR]不会。看看下面这个例子:
[CODE=php]
// create a string
$string = 'pp';

// look for a match
echo preg_match("/ph+p/", $string, $matches);

?>
[/CODE]
上面的脚本输出结果将会是0。因为字符h没有在字符串中出现1次或多次。
接下来我们看看问号([FONT-COLOR=Red]?[/FONT-COLOR])元字符。这个元字符和我们上面讲的元字符含义差不多,只是[FONT-COLOR=Red]?[/FONT-COLOR]是匹配0次或1次。在下面的代码中,我们将会看到如果你想让某些字符是可选的,比如在澳大利亚电话号码是1234-5678这样的格式,元字符[FONT-COLOR=Red]?[/FONT-COLOR]将会很有帮助。
[CODE=php]

// create a string
$string = '12345678';

// look for a match
echo preg_match("/1234-?5678/", $string, $matches);

?>
[/CODE]
上面的代码会输出结果1。这是因为?匹配了字符'-'0次。
把字符串改为'1234-5678'将会得到同样的结果。
[CODE=php]

// create a string
$string = '1234-5678';

// look for a match
echo preg_match("/1234-?5678/", $string, $matches);

?>
[/CODE]
接下来我们看看大括号([FONT-COLOR=Red]{}[/FONT-COLOR])元字符。它只是简单的指定匹配在它前面的字符的次数,或是指定一个范围。现在我们来匹配这样的一个字符串:字符串'PHP'后面跟着3个数字。
[CODE=php]

// create a string
$string = 'PHP123';

// look for a match
echo preg_match("/PHP[0-9]{3}/", $string, $matches);

?>
[/CODE]
我们看到模式字符串[FONT-COLOR=Red]PHP[0-9][/FONT-COLOR](0-9之间的任意数字)[FONT-COLOR=Red]{3}[/FONT-COLOR](3次)和字符串'PHP123'匹配成功。

九、特殊字符序列

反斜线也被用在字符序列中。什么是字符序列呢?
字符序列就是那些预定义的字符集,你可以再类中使用它。
[CODE]
\d - Matches any numeric character - same as [0-9]匹配任意数字字符
\D - Matches any non-numeric character - same as [^0-9]匹配任意非数字字符
\s - Matches any whitespace character - sames as [ \t\n\r\f\v]匹配任意空格字符
\S - Matches any non-whitespace character - same as [^ \t\n\r\f\v]匹配任意非空格字符
\w - Matches any alphanumeric character - same as [a-zA-Z0-9_]匹配任意字母数字字符
\W - Matches any non-alphanumeric character - same as [^a-zA-Z0-9_]匹配任意非字母数字字符
[/CODE]
运用上面的字符序列,我们可以再我们的模式字符串中使用,这样可以减少代码长度。看看下面的代码,你是否能说出输出结果:
[CODE=php]
// create a string
$string = 'ab-ce*fg@ hi & jkl(mnopqr)stu+vw?x yz0>1234<567890';

// match our pattern containing a special sequence
preg_match_all("/[\w]/", $string, $matches);

// loop through the matches with foreach
foreach($matches[0] as $value)
{
echo $value;
}
?>
[/CODE]
我们来看看是如何运行的。我们用\w来匹配出任意字母数字字符,因此输出结果是:
abcefghijklmnopqrstuvwxyz0123456789
这可以用来过滤用户名中的一些你不想要的非法字符。
运用同样的方法,我们可以一个字符串不以数字开头:
[CODE=php]
// create a string
$string = '2 bad for perl';

// echo our string
if(preg_match("/^\d/", $string))
{
echo 'String begins with a number';
}
else
{
echo 'String does not begin with a number';
}
?>
[/CODE]
[/FONT-SIZE]

已经有(0)位网友发表了评论,你也评一评吧!
原创文章如转载,请注明:转载自Eddy Blog
原文地址:http://www.rrgod.com/webdesign/854.html     欢迎订阅Eddy Blog

记住我的信息,下次不用再输入 欢迎给Eddy Blog留言