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脚本的10个技巧(1)
Oct 09 PHP
php flv视频时间获取函数
Jun 29 PHP
表格展示无限级分类(PHP版)
Aug 21 PHP
PHP CLI模式下的多进程应用分析
Jun 03 PHP
PHP在不同页面间传递Json数据示例代码
Jun 08 PHP
使用PHP函数scandir排除特定目录
Jun 12 PHP
getimagesize获取图片尺寸实例
Nov 15 PHP
SSO单点登录的PHP实现方法(Laravel框架)
Mar 23 PHP
php、mysql查询当天,查询本周,查询本月的数据实例(字段是时间戳)
Feb 04 PHP
PHP扩展Swoole实现实时异步任务队列示例
Apr 13 PHP
laravel-admin 实现在指定的相册下添加照片
Oct 21 PHP
laravel 解决强制跳转 https的问题
Oct 22 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
PHP实现用户认证及管理完全源码
2007/03/11 PHP
如何用PHP实现插入排序?
2013/04/10 PHP
Destoon旺旺无法正常显示,点击提示“会员名不存在”的解决办法
2014/06/21 PHP
php短网址和数字之间相互转换的方法
2015/03/13 PHP
PHP技术开发微信公众平台
2015/07/22 PHP
php7安装mongoDB扩展的方法分析
2017/08/02 PHP
thinkPHP5框架闭包函数与子查询传参用法示例
2018/08/02 PHP
JS 页面自动加载函数(兼容多浏览器)
2009/05/18 Javascript
扩展easyui.datagrid,添加数据loading遮罩效果代码
2010/11/02 Javascript
jQuery boxy弹出层插件中文演示及使用讲解
2011/02/24 Javascript
深入解析JavaScript的闭包机制
2015/10/20 Javascript
纯js实现手风琴效果
2020/04/17 Javascript
nodejs 图解express+supervisor+ejs的用法(推荐)
2017/09/08 NodeJs
BootStrap 标题设置跨行无效的解决方法
2017/10/25 Javascript
vue2里面ref的具体使用方法
2017/10/27 Javascript
Vue中使用Sortable的示例代码
2018/04/07 Javascript
Spring boot 和Vue开发中CORS跨域问题解决
2018/09/05 Javascript
小程序二次贝塞尔曲线实现购物车商品曲线飞入效果
2019/01/07 Javascript
[10:14]2018DOTA2国际邀请赛寻真——paiN Gaming不仅为自己而战
2018/08/14 DOTA
Python中join和split用法实例
2015/04/14 Python
Python中强大的命令行库click入门教程
2016/12/26 Python
Python字符串处理实现单词反转
2017/06/14 Python
python3写爬取B站视频弹幕功能
2017/12/22 Python
Python socket实现的简单通信功能示例
2018/08/21 Python
在 Pycharm 安装使用black的方法详解
2020/04/02 Python
高街生活方式全球在线商店:AZBRO
2017/08/26 全球购物
英国女士和男士时尚服装网上购物:Top Labels Online
2018/03/25 全球购物
鞋类设计与工艺专业销售求职信
2013/11/01 职场文书
财务工作个人求职的自我评价
2013/12/19 职场文书
校园活动策划书范文
2014/01/10 职场文书
干部对照检查材料范文
2014/08/26 职场文书
2014县委书记党的群众路线教育实践活动对照检查材料思想汇报
2014/09/22 职场文书
2016五一手机促销广告语
2016/01/28 职场文书
交通事故协议书范本
2016/03/19 职场文书
微信小程序调用python模型
2022/04/21 Python
mysql 体系结构和存储引擎介绍
2022/05/06 MySQL