Php正则表达式在嵌套数组中返回重复

Php正则表达式在嵌套数组中返回重复,php,regex,Php,Regex,我正在尝试获取php脚本中包含的所有文件的列表 我正在读取整个文件,其中包含以下内容: <?php echo 'Hello there'; include 'some_functions.php'; echo 'Trying to find some includes.'; include 'include_me.php'; echo 'Testtest.'; ?> 当我进行这场比赛时,我得到了预期的结果。。。这是两个include部

我正在尝试获取php脚本中包含的所有文件的列表

我正在读取整个文件,其中包含以下内容:

<?php
    echo 'Hello there';

    include 'some_functions.php';

    echo 'Trying to find some includes.';

    include 'include_me.php';

    echo 'Testtest.';
?>
当我进行这场比赛时,我得到了预期的结果。。。这是两个include部分,但我也得到了完全相同的内容的重复,或者include语句的随机块。以下是一个输出示例:

    Array ( 
[0] => Array ( [0] => include 'some_functions.php'; [1] => include 'include_me.php'; ) 
[1] => Array ( [0] => include 'some_functions.php'; [1] => include 'include_me.php'; ) ) 
如您所见,它多次嵌套具有相同结果的数组。对于每个include语句,我需要数组中的1项,没有重复,没有嵌套数组

我在使用这些正则表达式时遇到了一些问题,所以提供一些指导是很好的。谢谢您的时间。

如果脚本未包含,请使用或内置

我正在搜索另一个文件的字符串内容,而不是 当前文件

那么你最好的选择就是标记器。试试这个:

$scriptPath = '/full/path/to/your/script.php';
$tokens = token_get_all(file_get_contents($scriptPath));
$matches = array();
$incMode = null;

foreach($tokens as $token){

  // ";" should end include stm.
  if($incMode && ($token === ';')){
    $matches[] = $incMode;
    $incMode = array();
  }

  // keep track of the code if inside include statement
  if($incMode){
    $incMode[1] .= is_array($token) ? $token[1] : $token;
    continue;
  }  

  if(!is_array($token))
    continue;

  // start of include stm.
  if(in_array($token[0], array(T_INCLUDE, T_INCLUDE_ONCE, T_REQUIRE, T_REQUIRE_ONCE)))
    $incMode = array(token_name($token[0]), '');
}

print_r($matches); // array(token name, code)
请阅读,如何工作

数组中的第一项-它返回所有文本,这是正则表达式。 数组中的下一个项-即括号中正则表达式中的文本

你应该使用$matches[1]

这个怎么样

<?php
  preg_match_all( "/include(_once)?\s*\(?\s*(\"|')(.*?)\.php(\"|')\s*\)?\s*;?/i", $this->file_contents, $matches );
  // for file names
  print_r( $matches[3] );
  // for full lines
  print_r( $matches[0] );
?>

为什么要这样从php文件中提取?我将用它试图包含的文件的内容替换include语句。您的正则表达式没有意义,只需删除{1}部分,使其成为include.*?;。除此之外,这就是preg_match_的工作原理。哎哟,为什么不让include做它的工作呢?谢谢你的反馈。我知道这是毫无意义的,我只是不断修改它,试图让它做我想要的。达贡,没有什么好理由。我只想制作一个脚本,它可以捕获所有包含的文件,并创建一个具有相同功能的独立脚本。这更像是一个实验。我不相信这会起作用,因为我正在搜索其他文件内容的字符串,而不是当前文件。感谢更新的令牌方法。我得出的结论是,这是一个比我认为需要使用的正则表达式更好的解决方案。谢谢你给我带来了一个更好的方法。这很好,谢谢。但是我需要知道include语句中引号之间的整个路径,这就是为什么我试图抓住include和分号之间的所有内容。我会到处玩,看看能不能修改一下。感谢您的回复。如果您需要有关引号的所有内容,请从正则表达式中删除\.php,使其成为/include|u一次?\s*\?\s*\\\\\\\\\\\\\'.\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\非常感谢。我接受了你所说的和yAnTar所做的评论,找到了一些似乎有效的方法。我很感谢你的帮助。我希望你更新正则表达式来处理常量,这样我可以给你另一个失败的例子:但我很高兴看到你没有这样做,并且也使用了标记器。使用正则表达式来解析PHP是很愚蠢的…非常酷。我不知道什么都有。这是一个非常好的方法,我喜欢它。它比正则表达式整洁得多,工作得更好。感谢您的反馈和一个比我最初所想的更好的解决方案。我浏览了文档中的所有文本,现在明白了您的意思。当我从表达式中删除括号时,它只返回每个include一次。它仍然在单个嵌套数组中,但我可以使用它。谢谢你的回复,我不知道我误解了函数的工作原理。
<?php
  preg_match_all( "/include(_once)?\s*\(?\s*(\"|')(.*?)\.php(\"|')\s*\)?\s*;?/i", $this->file_contents, $matches );
  // for file names
  print_r( $matches[3] );
  // for full lines
  print_r( $matches[0] );
?>
<?php
  $tokens = token_get_all( $this->file_contents );
  $files  = array();
  $index  = 0;
  $found  = false;
  foreach( $tokens as $token ) {
    // in php 5.2+ Line numbers are returned in element 2
    $token  = ( is_string( $token ) ) ? array( -1, $token, 0 ) : $token;
    switch( $token[0] ) {
      case T_INCLUDE:
      case T_INCLUDE_ONCE:
      case T_REQUIRE:
      case T_REQUIRE_ONCE:
        $found  = true;
        if ( isset( $token[2] ) ) {
          $index  = $token[2];
        }
        $files[$index]  = null;
      break;

      case T_COMMENT:
      case T_DOC_COMMENT:
      case T_WHITESPACE:
      break;

      default:
        if ( $found && $token[1] === ";" ) {
          $found  = false;
          if ( !isset( $token[2] ) ) {
            $index++;
          }
        }
        if ( $found ) {
          if ( in_array( $token[1], array( "(", ")" ) ) ) {
            continue;
          }
          if ( $found ) {
            $files[$index]  .=  $token[1];
          }
        }
      break;
    }
  }
  // if your php version is above 5.2
  // $files index will be line numbers
  print_r( $files );
?>