我正在尝试使用PHP正则表达式从php源代码中提取函数。到目前为止,我使用递归正则表达式来提取{}之间的所有内容,但它也匹配像if语句之类的东西。当我使用类似的东西时:
preg_match_all("/(function .*\(.*\))({([^{}]+|(?R))*})/", $data, $matches);
当文件中有多个函数时,它不起作用(可能是因为它在递归中也使用了'function'部分)。
有没有办法做到这一点?
示例文件:
<?php
if($useless)
{
echo "i don't want this";
}
function bla($wut)
{
echo "i do want this";
}
?>
由于
答案 0 :(得分:5)
正则表达式是错误的方法。考虑tokenizer或reflection
答案 1 :(得分:4)
从重复的问题移到此处:PHP, Regex and new lines
正则表达式解决方案:
$regex = '~
function #function keyword
\s+ #any number of whitespaces
(?P<function_name>.*?) #function name itself
\s* #optional white spaces
(?P<parameters>\(.*?\)) #function parameters
\s* #optional white spaces
(?P<body>\{.*?\}) #body of a function
~six';
if (preg_match_all($regex, $input, $matches)) {
print_r($matches);
}
P.S。 如上所述,tokenizer是最好的方式。
答案 2 :(得分:1)
正则表达式在正文中接受递归花括号
我知道有一个选择的答案,但是如果无法使用tokenizer,这是一个简单的正则表达式,可以从php代码中提取函数(名称,参数和主体)。
与上述Ioseb答案的主要区别在于,此正则表达式接受主体中包含递归花括号的情况,这意味着它在第一个花括号关闭后不会停止。
/function\s+(?<name>\w+)\s*\((?<param>[^\)]*)\)\s*(?<body>\{(?:[^{}]+|(?&body))*\})/
说明
/ # delimiter
function # function keyword
\s+ # at least one whitespace
(?<name>\w+) # function name (a word) => group "name"
\s* # optional whitespace(s)
\((?<param>[^\)]*)\) # function parameters => group "param"
\s* # optional whitespace(s)
(?<body>\{(?:[^{}]+|(?&body))*\}) # body function (recursive curly brackets allowed) => group "body"
/ # delimiter
示例
$data = '
<?php
function my_function($param){
if($param === true){
// This is true
}else if($param === false){
// This is false
}else{
// This is not
}
}
?>
';
preg_match_all("/function\s+(?<name>\w+)\s*\((?<param>[^\)]*)\)\s*(?<body>\{(?:[^{}]+|(?&body))*\})/", $data, $matches);
print_r($matches['body']);
/*
Array
(
[0] => {
if($param === true){
// This is true
}else if($param === false){
// This is false
}else{
// This is not
}
}
)
*/
限制
括号必须保持平衡。 即,此身体将被部分提取:
function my_function(){
echo "A curly bracket : }";
echo "Another curly bracket : {";
}
/*
Array
(
[0] => {
echo "A curly bracket : }
)
*/