Php正则表达式在嵌套数组中返回重复
我正在尝试获取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
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 );
?>