1. PHP 变量的作用域
参见 php 手册: Language Reference - Variables - Variable scope
<?php $a = 1; /* global scope */ function test() { echo $a; /* reference to local scope variable */ } test(); ?>
在 C 语言中,变量的作用域是从声明到文件结束,所以会误以为能输出 a 的值。
但是,和 C 语言的全局变量不同,php的全局变量必须在函数体内进行声明。
PHP 中声明全局变量的方式:
- 使用 global 关键字: 表明本变量是全局的,而非local。
可以在函数体外使用global,场景:文件A中,在函数体外使用了global。文件B包含A,这是合法的。
<?php $a = 1; $b = 2; function Sum() { global $a, $b; $b = $a + $b; } Sum(); echo $b; ?>
- 使用 $GLOBALS 数组: $GLOBALS属于superglobal,superglobal 在函数体内不需要global声明,就能任意使用,比如 $_POST。
<?php $a = 1; $b = 2; function Sum() { $GLOBALS['b'] = $GLOBALS['a'] + $GLOBALS['b']; } Sum(); echo $b; ?>
- 使用static关键字:
a) 只能在函数内使用
b) 通过表达式给static变量赋值会造成parse错误

<?php function test() { static $count = 0; $count++; echo $count; if ($count < 10) { test(); } $count--; } ?>
2. preg_match_all 的返回值研究
int preg_match_all ( string $pattern , string $subject [, array &$matches [, int $flags = PREG_PATTERN_ORDER [, int $offset = 0 ]]] )
先前只知道match是一个二维数组,一直用$matches[0] 在读取所有匹配的内容。
今天 print_r($matches) 时看到还有$matches[1]和$matches[2],遂决定了解清楚。
缺省情况下,$flags 值为 PREG_PATTERN_ORDER。对应的:
Orders results so that $matches[0] is an array of full pattern matches, $matches[1] is an array of strings matched by the first parenthesized subpattern, and so on.
$matches[1]表示第一个括号中匹配到的内容,$matches[2]。。。等依次存储匹配到的内容。
我们知道,使用正则表达式的 后向引用 可以很容易的获取匹配到的内容:
<?php $str = 'foobar: 2008'; preg_match('/(?P<name>\w+): (?P<digit>\d+)/', $str, $matches); /* This also works in PHP 5.2.2 (PCRE 7.0) and later, however * the above form is recommended for backwards compatibility */ // preg_match('/(?<name>\w+): (?<digit>\d+)/', $str, $matches); print_r($matches); ?> 输出结果为: Array ( [0] => foobar: 2008 [name] => foobar [1] => foobar [digit] => 2008 [2] => 2008 )
那为什么不都使用 后向引用 来进行精确存储呢?
在PHP手册preg_match函数的changelog写到:
5.2.2 Named subpatterns now accept the syntax (?<name>) and (?'name') as well as (?P<name>). Previous versions accepted only (?P<name>).
也就是从PHP V5.2.2 之后才支持这种写法。而$matches[n] 是最先支持的。
因此,$matches[n] 更通用。
3. 实现一个简单的正则表达式引擎
题目要求:
Write a parser for a simplified regular expression
On an alphabet set [a-z], a simplified regular expression is much simpler than the normal regular expression.
It has only two meta characters: '.' and '*'.
'.' -- exact one arbitrary character match.
'*' -- zero or more arbitrary character match.
--------------------------
举个例子,表达式 ab.*d 能匹配 'abcd', 'abccd', 'abad'. 不能匹配'abc', ' '(空字符串), 'abd'.
两年前,绿盟科技笔试题最后一题即为此。
这里先放上别人的解决方案,过两天再看:代码之美——30行代码实现正则表达式匹配器
1 /*match :在text中查找regexp*/ 2 int match(char *regexp,char *text) 3 { 4 if(regexp[0] == '^') 5 return matchhere(regexp+1,text); 6 do{ /*即使字符串为空也必须检查*/ 7 if (matchhere(regexp,text)) 8 return 1; 9 }while (*text++!= '\0'); 10 return 0; 11 } 12 /*matchhere在text的开头查找regexp*/ 13 int matchhere(char *regexp,char *text) 14 { 15 if (regexp[0] == '\0') 16 return 1; 17 if (regexp[1] == '*') 18 return matchstar(regexp[0],regexp+2,text); 19 if (regexp[0] == '$' && regexp[1]=='\0') 20 return *text == '\0'; 21 if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text)) 22 return matchhere(regexp+1,text+1); 23 return 0; 24 } 25 /*matchstar :在text的开头查找C*regexp*/ 26 int matchstar (int c,char *regexp,char *text) 27 { 28 do { /*通配符*匹配零个或多个实例*/ 29 if (matchhere(regexp,text)) 30 return 1; 31 }while (*text!='\0' && (*text++ ==c || c== '.')); 32 return 0; 33 }