POSIX 风格和兼容 Perl 风格两种正则表达式主要函数的类比(preg_match, preg_replace, ereg, ereg_replace)


Posted in PHP onOctober 12, 2010

首先来看看 POSIX 风格正则表达式的两个主要函数:

ereg 函数:(正则表达式匹配)

格式:int ereg ( string pattern, string string [, array ®s] )
注意:使用 Perl 兼容正则表达式语法的 preg_match() 函数通常是比 ereg() 更快的替代方案。(一般的话还是使用 preg_match() ,比较好勒~~)

以区分大小写的方式在 string 中寻找与给定的正则表达式 pattern 所匹配的子串。如果找到与 pattern 中圆括号内的子模式相匹配的子串并且函数调用给出了第三个参数 regs,则匹配项将被存入 regs 数组中。$regs[1] 包含第一个左圆括号开始的子串,$regs[2] 包含第二个子串,以此类推。$regs[0] 包含整个匹配的字符串。

返回值:如果在 string 中找到 pattern 模式的匹配则返回 所匹配字符串的长度,如果没有找到匹配或出错则返回 FALSE。如果没有传递入可选参数 regs 或者所匹配的字符串长度为 0,则本函数返回 1。

来看看 ereg() 函数的例子:

以下代码片断接受 ISO 格式的日期(YYYY-MM-DD)然后以 DD.MM.YYYY 格式显示:

<?php 
if (ereg ("([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})", $date, $regs)) { 
echo "$regs[3].$regs[2].$regs[1]"; 
} else { 
echo "Invalid date format: $date"; 
} 
?>

-----------------------------------------------------------------------------------
ereg_replace 函数:(正则表达式替换)

格式:string ereg_replace ( string pattern, string replacement, string string )
函数说明:
本函数在 string 中扫描与 pattern 匹配的部分,并将其替换为 replacement。
返回替换后的字符串。(如果没有可供替换的匹配项则会返回原字符串。)
如果 pattern 包含有括号内的子串,则 replacement 可以包含形如 \\digit 的子串,这些子串将被替换为数字表示的第几个括号内的子串;\\0 则包含了字符串的整个内容。最多可以用九个子串。括号可以嵌套,此情形下以左圆括号来计算顺序。
如果未在 string 中找到匹配项,则 string 将原样返回。
来看看这个函数例子吧:
1,下面的代码片断输出 "This was a test" 三次:

<?php 
$string = "This is a test"; 
echo str_replace(" is", " was", $string); 
echo ereg_replace("( )is", "\\1was", $string); 
echo ereg_replace("(( )is)", "\\2was", $string); 
?>

要注意的一点是如果在 replacement 参数中使用了整数值,则可能得不到所期望的结果。这是因为ereg_replace() 将把数字作为字符的序列值来解释并应用之。例如:
2,replacement 参数为整数时的例子:
<?php 
/* 不能产生出期望的结果 */ 
$num = 4; 
$string = "This string has four words."; 
$string = ereg_replace('four', $num, $string); 
echo $string; /* Output: 'This string has words.' */ 
/* 本例工作正常 */ 
$num = '4'; 
$string = "This string has four words."; 
$string = ereg_replace('four', $num, $string); 
echo $string; /* Output: 'This string has 4 words.' */ 
?>

3,将 URL 替换为超链接:
$text = ereg_replace("[[:alpha:]]+://[^<>[:space:]]+[[:alnum:]/]", 
"<a href=\"\\0\">\\0</a>", $text);

提示: preg_replace() 函数使用了 Perl 兼容正则表达式语法,通常是比 ereg_replace() 更快的替代方案。
再来看看 Perl 兼容正则表达式的两个主要函数:
preg_match 函数:(进行正则表达式匹配)
格式:int preg_match ( string pattern, string subject [, array matches [, int flags]] )
函数说明:
在 subject 字符串中搜索与 pattern 给出的正则表达式相匹配的内容。
如果提供了 matches,则其会被搜索的结果所填充。$matches[0] 将包含与整个模式匹配的文本,$matches[1] 将包含与第一个捕获的括号中的子模式所匹配的文本,以此类推。
flags 可以是下列标记:
PREG_OFFSET_CAPTURE
如果设定本标记,对每个出现的匹配结果也同时返回其附属的字符串偏移量。注意这改变了返回的数组的值,使其中的每个单元也是一个数组,其中第一项为匹配字符串,第二项为其偏移量。本标记自 PHP 4.3.0 起可用。
flags 参数自 PHP 4.3.0 起可用。
preg_match() 返回 pattern 所匹配的次数。要么是 0 次(没有匹配)或 1 次,因为 preg_match() 在第一次匹配之后将停止搜索。preg_match_all() 则相反,会一直搜索到 subject 的结尾处。如果出错 preg_match() 返回 FALSE。
Tips: 如果只想查看一个字符串是否包含在另一个字符串中,不要用 preg_match()。可以用 strpos() 或 strstr() 替代,要快得多。
来看看它的例子吧:
例 1. 在文本中搜索“php”:
<?php 
// 模式定界符后面的 "i" 表示不区分大小写字母的搜索 
if (preg_match ("/php/i", "PHP is the web scripting language of choice.")) { 
print "A match was found."; 
} else { 
print "A match was not found."; 
} 
?>

例 2. 搜索单词“web”:
<?php 
/* 模式中的 \b 表示单词的边界,因此只有独立的 "web" 单词会被匹配, 
* 而不会匹配例如 "webbing" 或 "cobweb" 中的一部分 */ 
if (preg_match ("/\bweb\b/i", "PHP is the web scripting language of choice.")) { 
print "A match was found."; 
} else { 
print "A match was not found."; 
} 
if (preg_match ("/\bweb\b/i", "PHP is the website scripting language of choice.")) { 
print "A match was found."; 
} else { 
print "A match was not found."; 
} 
?>

例 3. 从 URL 中取出域名:
<?php 
// 从 URL 中取得主机名 
preg_match("/^(http:\/\/)?([^\/]+)/i", 
"http://www.php.net/index.html", $matches); 
$host = $matches[2]; 
// 从主机名中取得后面两段 
preg_match("/[^\.\/]+\.[^\.\/]+$/", $host, $matches); 
echo "domain name is: {$matches[0]}\n"; 
?>

本例将输出:
domain name is: php.net
-----------------------------------------------------------------------------------
preg_replace 函数:(执行正则表达式的搜索和替换)
格式:mixed preg_replace ( mixed pattern, mixed replacement, mixed subject [, int limit] )
函数说明:
在 subject 中搜索 pattern 模式的匹配项并替换为 replacement。如果指定了 limit,则仅替换 limit 个匹配,如果省略 limit 或者其值为 -1,则所有的匹配项都会被替换。
replacement 可以包含 \\n 形式或(自 PHP 4.0.4 起)$n 形式的逆向引用,首选使用后者。每个此种引用将被替换为与第 n 个被捕获的括号内的子模式所匹配的文本。n 可以从 0 到 99,其中 \\0 或 $0 指的是被整个模式所匹配的文本。对左圆括号从左到右计数(从 1 开始)以取得子模式的数目。
对替换模式在一个逆向引用后面紧接着一个数字时(即:紧接在一个匹配的模式后面的数字),不能使用熟悉的 \\1 符号来表示逆向引用。举例说 \\11,将会使 preg_replace() 搞不清楚是想要一个 \\1 的逆向引用后面跟着一个数字 1 还是一个 \\11 的逆向引用。本例中的解决方法是使用 \${1}1。这会形成一个隔离的 $1 逆向引用,而使另一个 1 只是单纯的文字。
来看看它的例子:
例 1. 逆向引用后面紧接着数字的用法:
<?php 
$string = "April 15, 2003"; 
$pattern = "/(\w+) (\d+), (\d+)/i"; 
$replacement = "\${1}1,\$3"; 
print preg_replace($pattern, $replacement, $string); 
/* Output 
====== 
April1,2003 
*/ 
?>

如果搜索到匹配项,则会返回被替换后的 subject,否则返回原来不变的 subject。
preg_replace() 的每个参数(除了 limit)都可以是一个数组。如果 pattern 和 replacement 都是数组,将以其键名在数组中出现的顺序来进行处理。这不一定和索引的数字顺序相同。如果使用索引来标识哪个 pattern 将被哪个 replacement 来替换,应该在调用 preg_replace() 之前用 ksort() 对数组进行排序。
例 2. 在 preg_replace() 中使用索引数组:
<?php 
$string = "The quick brown fox jumped over the lazy dog."; 
$patterns[0] = "/quick/"; 
$patterns[1] = "/brown/"; 
$patterns[2] = "/fox/"; 
$replacements[2] = "bear"; 
$replacements[1] = "black"; 
$replacements[0] = "slow"; 
print preg_replace($patterns, $replacements, $string); 
/* Output 
====== 
The bear black slow jumped over the lazy dog. 
*/ 
/* By ksorting patterns and replacements, 
we should get what we wanted. */ 
ksort($patterns); 
ksort($replacements); 
print preg_replace($patterns, $replacements, $string); 
/* Output 
====== 
The slow black bear jumped over the lazy dog. 
*/ 
?>

如果 subject 是个数组,则会对 subject 中的每个项目执行搜索和替换,并返回一个数组。
如果 pattern 和 replacement 都是数组,则 preg_replace() 会依次从中分别取出值来对 subject 进行搜索和替换。如果 replacement 中的值比 pattern 中的少,则用空字符串作为余下的替换值。如果 pattern 是数组而 replacement 是字符串,则对 pattern 中的每个值都用此字符串作为替换值。反过来则没有意义了。
/e 修正符使 preg_replace() 将 replacement 参数当作 PHP 代码(在适当的逆向引用替换完之后)。提示:要确保 replacement 构成一个合法的 PHP 代码字符串,否则 PHP 会在报告在包含 preg_replace() 的行中出现语法解析错误。
例 3. 替换数个值:
<?php 
$patterns = array ("/(19|20)(\d{2})-(\d{1,2})-(\d{1,2})/", 
"/^\s*{(\w+)}\s*=/"); 
$replace = array ("\\3/\\4/\\1\\2", "$\\1 ="); 
print preg_replace ($patterns, $replace, "{startDate} = 1999-5-27"); 
?>

本例将输出:
$startDate = 5/27/1999
例 4. 使用 /e 修正符:
<?php 
preg_replace ("/(<\/?)(\w+)([^>]*>)/e", 
"'\\1'.strtoupper('\\2').'\\3'", 
$html_body); 
?>

这将使输入字符串中的所有 HTML 标记变成大写。
例 5. 将 HTML 转换成文本:
<?php 
// $document 应包含一个 HTML 文档。 
// 本例将去掉 HTML 标记,javascript 代码 
// 和空白字符。还会将一些通用的 
// HTML 实体转换成相应的文本。 
$search = array ("'<script[^>]*?>.*?</script>'si", // 去掉 javascript 
"'<[\/\!]*?[^<>]*?>'si", // 去掉 HTML 标记 
"'([\r\n])[\s]+'", // 去掉空白字符 
"'&(quot|#34);'i", // 替换 HTML 实体 
"'&(amp|#38);'i", 
"'&(lt|#60);'i", 
"'&(gt|#62);'i", 
"'&(nbsp|#160);'i", 
"'&(iexcl|#161);'i", 
"'&(cent|#162);'i", 
"'&(pound|#163);'i", 
"'&(copy|#169);'i", 
"'&#(\d+);'e"); // 作为 PHP 代码运行 
$replace = array ("", 
"", 
"\\1", 
"\"", 
"&", 
"<", 
">", 
" ", 
chr(161), 
chr(162), 
chr(163), 
chr(169), 
"chr(\\1)"); 
$text = preg_replace ($search, $replace, $document); 
?>

The End…
PHP 相关文章推荐
PHP 开源AJAX框架14种
Aug 24 PHP
PHP 命令行参数详解及应用
May 18 PHP
PHP判断远程url是否有效的几种方法小结
Oct 08 PHP
解析使用substr截取UTF-8中文字符串出现乱码的问题
Jun 20 PHP
深入解析php中的foreach函数
Aug 31 PHP
php判断字符串在另一个字符串位置的方法
Feb 27 PHP
ThinkPHP有变量的where条件分页实例
Nov 03 PHP
php轻量级的性能分析工具xhprof的安装使用
Aug 12 PHP
常用PHP数组排序函数归纳
Aug 08 PHP
PHP实现图的邻接矩阵表示及几种简单遍历算法分析
Nov 24 PHP
在Laravel5.6中使用Swoole的协程数据库查询
Jun 15 PHP
PHP convert_cyr_string()函数讲解
Feb 13 PHP
献给php初学者(入门学习经验谈)
Oct 12 #PHP
发款php蜘蛛统计插件只要有mysql就可用
Oct 12 #PHP
php更改目录及子目录下所有的文件后缀扩展名的代码
Oct 12 #PHP
利用php+mysql来做一个功能强大的在线计算器
Oct 12 #PHP
发一个php简单的伪原创程序,配合商城采集用的
Oct 12 #PHP
php知道与问问的采集插件代码
Oct 12 #PHP
php笔记之常用文件操作
Oct 12 #PHP
You might like
支持数组的ADDSLASHES的php函数
2010/02/16 PHP
基于laravel制作APP接口(API)
2016/03/15 PHP
thinkPHP实现的联动菜单功能详解
2017/05/05 PHP
解决laravel id非自增 模型取回为0 的问题
2019/10/11 PHP
关于html+ashx开发中几个问题的解决方法
2011/07/18 Javascript
gridpanel动态加载数据的实例代码
2013/07/18 Javascript
使用js简单实现了tree树菜单
2013/11/20 Javascript
从JQuery源码分析JavaScript函数的apply方法与call方法
2014/09/25 Javascript
javascript关于运动的各种问题经典总结
2015/04/27 Javascript
jQuery实现鼠标滑向当前图片高亮显示并且其它图片变灰的方法
2015/07/27 Javascript
JQUERY表单暂存功能插件分享
2016/02/23 Javascript
JQuery实现简单的服务器轮询效果实例
2016/03/31 Javascript
JS实现左右无缝轮播图代码
2016/05/01 Javascript
Vue.js快速入门教程
2016/09/07 Javascript
javascript 网页进度条简单实例
2017/02/22 Javascript
详解EasyUi控件中的Datagrid
2017/08/23 Javascript
js传递数组参数到后台controller的方法
2018/03/29 Javascript
javascript实现考勤日历功能
2018/11/29 Javascript
python去除文件中空格、Tab及回车的方法
2016/04/12 Python
Python 通过调用接口获取公交信息的实例
2018/12/17 Python
基于python的ini配置文件操作工具类
2019/04/24 Python
Python列表与元组的异同详解
2019/07/02 Python
python中tkinter的应用:修改字体的实例讲解
2019/07/17 Python
Python学习笔记之列表和成员运算符及列表相关方法详解
2019/08/22 Python
python3 requests库实现多图片爬取教程
2019/12/18 Python
python GUI库图形界面开发之PyQt5简单绘图板实例与代码分析
2020/03/08 Python
使用OpenCV去除面积较小的连通域
2020/07/05 Python
Django如何实现防止XSS攻击
2020/10/13 Python
Python jieba库分词模式实例用法
2021/01/13 Python
MyFrenchPharma中文网:最大的法国药妆平台
2016/10/07 全球购物
商家认证委托书格式
2014/10/16 职场文书
计划生育工作汇报
2014/10/28 职场文书
基层党员学习党的群众路线教育实践活动心得体会
2014/11/04 职场文书
2015年共青团工作总结
2015/05/15 职场文书
windows server2012 R2下安装PaddleOCR服务的的详细步骤
2022/09/23 Servers
table设置超出部分隐藏,鼠标移上去显示全部内容的方法
2022/12/24 HTML / CSS