我是正则表达式的新手,这对我来说太先进了.所以我在这里问专家.
问题 我想从php define()中检索常量/值
DEFINE('TEXT', 'VALUE');
Run Code Online (Sandbox Code Playgroud)
基本上我想要一个正则表达式能够返回常量的名称,并从上面的行返回常量的值.只是文字和价值.这甚至可能吗?
为什么我需要它?我正在处理语言文件,我希望得到所有的夫妻(名字,价值)并把它们放在数组中.我设法用str_replace()和trim()等来完成它.但是这种方式很长,我相信使用单行正则表达式可以使它变得更容易.
注意:VALUE也可能包含转义单引号.例:
DEFINE('TEXT', 'J\'ai');
Run Code Online (Sandbox Code Playgroud)
我希望我不要求太复杂的事情.:)
问候
cle*_*tus 17
对于任何类型的基于语法的解析,正则表达式通常是一个糟糕的解决方案.即使是大量的语法(比如算术)也有嵌套,而且正在嵌套(特别是)正则表达式才会失败.
幸运的是,PHP通过token_get_all()函数访问PHP解释器使用的相同词法分析器,为您提供了更好的解决方案.给它一个PHP代码的字符流,它将它解析为令牌("lexemes"),你可以用一个非常简单的有限状态机做一些简单的解析.
运行这个程序(它作为test.php运行,所以它自己尝试).该文件故意格式错误,所以你可以看到它轻松处理.
<?
define('CONST1', 'value' );
define (CONST2, 'value2');
define( 'CONST3', time());
define('define', 'define');
define("test", VALUE4);
define('const5', //
'weird declaration'
) ;
define('CONST7', 3.14);
define ( /* comment */ 'foo', 'bar');
$defn = 'blah';
define($defn, 'foo');
define( 'CONST4', define('CONST5', 6));
header('Content-Type: text/plain');
$defines = array();
$state = 0;
$key = '';
$value = '';
$file = file_get_contents('test.php');
$tokens = token_get_all($file);
$token = reset($tokens);
while ($token) {
// dump($state, $token);
if (is_array($token)) {
if ($token[0] == T_WHITESPACE || $token[0] == T_COMMENT || $token[0] == T_DOC_COMMENT) {
// do nothing
} else if ($token[0] == T_STRING && strtolower($token[1]) == 'define') {
$state = 1;
} else if ($state == 2 && is_constant($token[0])) {
$key = $token[1];
$state = 3;
} else if ($state == 4 && is_constant($token[0])) {
$value = $token[1];
$state = 5;
}
} else {
$symbol = trim($token);
if ($symbol == '(' && $state == 1) {
$state = 2;
} else if ($symbol == ',' && $state == 3) {
$state = 4;
} else if ($symbol == ')' && $state == 5) {
$defines[strip($key)] = strip($value);
$state = 0;
}
}
$token = next($tokens);
}
foreach ($defines as $k => $v) {
echo "'$k' => '$v'\n";
}
function is_constant($token) {
return $token == T_CONSTANT_ENCAPSED_STRING || $token == T_STRING ||
$token == T_LNUMBER || $token == T_DNUMBER;
}
function dump($state, $token) {
if (is_array($token)) {
echo "$state: " . token_name($token[0]) . " [$token[1]] on line $token[2]\n";
} else {
echo "$state: Symbol '$token'\n";
}
}
function strip($value) {
return preg_replace('!^([\'"])(.*)\1$!', '$2', $value);
}
?>
Run Code Online (Sandbox Code Playgroud)
输出:
'CONST1' => 'value'
'CONST2' => 'value2'
'CONST3' => 'time'
'define' => 'define'
'test' => 'VALUE4'
'const5' => 'weird declaration'
'CONST7' => '3.14'
'foo' => 'bar'
'CONST5' => '6'
Run Code Online (Sandbox Code Playgroud)
这基本上是一个查找模式的有限状态机:
function name ('define')
open parenthesis
constant
comma
constant
close parenthesis
Run Code Online (Sandbox Code Playgroud)
在PHP源文件的词汇流中,将两个常量视为(名称,值)对.这样做它处理嵌套的define()语句(根据结果)并忽略空格和注释以及跨多行工作.
注意:我的deliberatley使它忽略了函数和变量是常量名称或值的情况,但你可以根据需要将它扩展到它.
值得指出的是,PHP在字符串方面非常宽容.它们可以用单引号,双引号或(在某些情况下)声明,完全没有引号.这可以(正如Gumbo所指出的那样)是一个对常量的模糊参考引用,你无法知道它是什么(无论如何都没有保证),给你一个chocie:
我个人会去(1)然后(3).
| 归档时间: |
|
| 查看次数: |
3296 次 |
| 最近记录: |