如何解析PHP项目,在代码中查找函数出现并在每次调用中检测被调用的参数?

时间:2013-10-09 18:00:40

标签: php regex replace

编辑:该函数的真实姓名是CB_t

考虑一个包含多个文件和文件夹的项目。 在整个项目中,我们使用不同的参数多次调用CB_t($ string ='')函数。 我需要的是以编程方式查找此函数的所有时间并使用参数创建数组。该参数始终为String。

代码示例:

文件1:

<?php
# Some code ....

$a = CB_t('A');
$b = CB_t("B");

# more code ...

文件2:

<?php
# Some code ....

$c = CB_t("ABC");
$d = CB_t('1938');

# more code ...

我需要的是解析所有代码并创建一个包含所有参数的数组。 我的上述示例的情况应该是这样的:

['A','B','ABC','1938']

以下是我到目前为止所尝试的并且没有给出好的结果,因为函数有时使用简单的引号调用,有时使用双引号或使用大写或小写。

    $search = "F(";
    $path = realpath(ROOT); // ROOT defined as project root folder 
    $fileList = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path), \RecursiveIteratorIterator::SELF_FIRST);
    $count = 0;$counter = 0;
    foreach ($fileList as $item) 
    {
        if ( $item->isFile() && substr($item->getPathName(), -4) =='.php')  // #1
        {

            $counter++;

            $file = file_get_contents($item->getPathName());


                if( strpos($file,trim($search)) !== false) {

                    $count++;

                    echo "<br>File no   : ".$count;
                    echo "<br>Filename  : ".$item->getFileName();
                    echo "<br>File path : ".$item->getPathName();
                    echo "<hr>";


                } // End file is php

            unset($file);

        } // End if #1

    } // End foreach

我认为这可以通过正则表达式以某种方式解决,但我不能很好地控制这部分。

提前致谢!

2 个答案:

答案 0 :(得分:1)

这可能有用。那里有一些额外的注释用于分支重置。捕获组1将为 包含字符串内容。

 Edit - If you want to make the regex into a C-style string, here it is:    

 "[Ff]\\s*\\(\\s*(?|\"([^\"\\\\]*(?:\\\\.[^\"\\\\]*)*)\"|'([^'\\\\]*(?:\\\\.[^'\\\\]*)*)')\\s*\\)"
 ---------------------------------------------------------


      #  [Ff]\s*\(\s*(?|"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)')\s*\)

      [Ff] 
      \s* 
      \(
      \s* 
      (?|
           " 
 br 1      (                              # (1 start)
                [^"\\]* 
                (?: \\ . [^"\\]* )*
    1      )                              # (1 end)
           "
        |  
           ' 
 br 1      (                              # (1 start)
                [^'\\]* 
                (?: \\ . [^'\\]* )*
    1      )                              # (1 end)
           '
      )
      \s* 
      \)

Edit2 - 用法示例:

 $string =
 "
 f('hello')
 F(\"world\")
 ";

 preg_match_all
      ( 
          "/[Ff]\\s*\\(\\s*(?|\"([^\"\\\\]*(?:\\\\.[^\"\\\\]*)*)\"|'([^'\\\\]*(?:\\\\.[^'\\\\]*)*)')\\s*\\)/",
          $string,
          $matches,
          PREG_PATTERN_ORDER
      );
  print_r( $matches[1] );

 -----------------------------
 Result:
 Array
 (
     [0] => hello
     [1] => world
 )

答案 1 :(得分:1)

我不确定正则表达式是否足够聪明,但这应该让你接近:

foreach ($fileList as $item) 
{
    if ( $item->isFile() && substr($item->getPathName(), -4) =='.php')  // #1
    {
        $counter++;

        $file = file_get_contents($item->getPathName());
        $matches= array();

        $count= preg_match_all('/\bCB_t\s*\(\s*[\'"](.*?)[\'"]\s*\)/i', $file, $matches);

        echo "<br>File no   : ".$count;
        echo "<br>Filename  : ".$item->getFileName();
        echo "<br>File path : ".$item->getPathName();
        echo "<hr>";

        unset($file);

        $total+= $count;
    } // End if #1

} // End foreach

正则表达式查找CB_t(或cb_t - 最后的i使其不区分大小写)后跟零个或多个空格,然后跟随(零个或多个空格(再次)后跟单引号或双引号。 (显然,这与使用可变参数调用CB_t的任何地方都不匹配,例如CB_t($somevar) - 您需要为此进行调整。)

然后使用调用preg_match_all的结果来计算页面上的匹配数。 (我也加了一个$总计 - 我在自己的测试中使用它!)

我知道正则表达式的一个问题是它仍将计算对注释中或另一个字符串中出现的CB_t的调用,例如

/* CB_t('fred'); */
$somevar= 'CB_t("fred")';

两者都会被计算在内。

希望它有所帮助!

(编辑粗心糊涂)

(再次编辑包括Galvic改进的RegExp并根据要求更改功能名称。)