一个PHP正则表达式从代码文件中提取php函数

时间:2010-03-21 20:00:15

标签: php regex function static-analysis

我正在尝试使用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";
}
?>

由于

3 个答案:

答案 0 :(得分:5)

正则表达式是错误的方法。考虑tokenizerreflection

答案 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 : }
)
*/