<!-- START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters -->
<!-- END RESERVED FOR FUTURE USE INCLUDE FILES--> 所有机器都会消耗输入,执行某种工作,然后生成输出。例如,电话把声能转换为电信号并重新转换回声频来启动对话。发动机吸
收燃料(蒸汽、裂变、汽油或者做大量的功)并将其转换为功。又或者将朗姆酒、冰块、酸橙和柑桂酒倒入调酒壶中,并且用力搅拌制作麦泰(或者,如果您希望调
制出更具有大都会特色的饮品,请尝试使用一点香槟酒和带果肉的梨汁饮料来享用贝利尼。调酒壶真是一个灵活而又非凡的工具)。
由于软件将转换数据,因此每个应用程序也是一台机器 —— 但是是一台 “虚拟”
机器,因为没有使用物理部件。例如,编译器期望获得源代码作为输入并将其转化为适于执行的二进制代码。气象建模工具将根据历史测量数据来生成预报。而图像
编辑器将消耗并生成像素,对每个像素或每组像素应用规则从而锐化图像或形成某种风格。
就像任何其他机器一样,软件应用程序期望获得某些 “原料”,例如数字列表、XML
模式中封装的数据或者协议。如果给程序提供错误的 “原料” —— 类型或形式不匹配 ——
则很可能得到无法预测的结果,甚至导致灾难。有句格言说得好,“错误的输入必然导致错误的输出”。
事实上,所有比较重要的问题都要求从错误数据中过滤出正确数据和/或拒绝错误数据以防止得到错误输出。对于 PHP
Web 应用程序来说也是如此。无论输入是来自手动形式还是来自编程式的 Asynchronous JavaScript + XML (Ajax)
请求,程序都必须在执行任何计算之前检查传入信息。可能要求数值属于某个范围或者被限定为整数。值可能需要匹配一种特定格式,如邮政编码。例如,美国的邮
政编码是五位数字加上可选的 “4 个”
限定号码,后者由连字符和四位附加数字组成。其他字符串可能是特定数目的字符,例如两个字母表示的美国各州的缩写。字符串最为棘手:PHP
应用程序必须对嵌入 SQL 查询、JavaScript 代码或者其他能够改变应用程序行为或有碍安全性的恶意操作程序保持警惕。
但是程序如何告知输入是数字还是遵循某个约定(例如邮政编码)?基本上,执行匹配需要使用一个小型解析器 ——
创建一个状态机、读取输入、处理标记、监视状态并生成结果。但是,即使是一个简单的解析器,也难于进行创建和维护。
幸运的是,由于模式匹配分析是最常见的计算需求,因此,随着时间的推移,一种特殊的简写方式(引擎)应运而生(大约从
UNIX® 出现之后),它可以减轻事务的工作量。正则表达式 (regex)
使用简明、易读的符号描述模式。给定一个正则表达式和数据,正则表达式引擎将得到数据是否匹配模式及匹配内容(如果找到匹配)等结果。
下面是应用从 UNIX 命令行实用程序 grep 中提取的正则表达式的简单示例,该实用程序将在一个或多个 UNIX
文本文件的内容中搜索指定模式。命令 grep -i -E '^Bat'
将搜索序列 beginning-of-line
(用
脱字符号 [^] 来表示),后面紧接着大写或小写字母 b、a
和 t
(使用 -i
选项将在模式匹配时忽略大小写,举例来说,也就是 B
和 b
是等效的)。因此,给出文件 heroes.txt:
清单 1. heroes.txt
Catwoman
Batman
The Tick
Black Cat
Batgirl
Danger Girl
Wonder Woman
Luke Cage
The Punisher
Ant Man
Dead Girl
Aquaman
SCUD
Blackbolt
Martian Manhunter
为了演示函数,让我们编写一个小型 PHP 应用程序,该应用程序将搜索单词列表以查找特定模式,遵循这种模式的单词和
regex 都是由传统的 Web 表单来提供的,并且结果都使用 simple print_r()
函数返回给浏览器。如果需要测试或改进 regex,则这种小型程序非常有用。
清单 2 显示了 PHP 代码。所有输入都是通过简单的 HTML
表单来提供的(为了简洁起见,不显示相应的表单,并且已经省略了用于捕捉 PHP 代码错误的代码)。
清单 2. 比较文本与模式
<?php
//
// divide the comma-separated list into individual words
// the third parameter, -1, permits a limitless number of matches
// the fourth parameter, PREG_SPLIT_NO_EMPTY, ignores empty matches
//
$words = preg_split( '/,/', $_REQUEST[ 'words' ], -1, PREG_SPLIT_NO_EMPTY );
//
// remove the leading and trailing spaces from each element
//
foreach ( $words as $key => $value ) {
$words[ $key ] = trim( $value );
}
//
// find the words that match the regular expression
//
$matches = preg_grep( "/${_REQUEST[ 'regex' ]}/", $words );
print_r( $_REQUEST['regex' ] );
echo( '<br /><br />' );
print_r( $words );
echo( '<br /><br />' );
print_r( $matches );
exit;
?>