PHP变量连接内部文件行

时间:2014-10-12 18:28:09

标签: php file concatenation

我的网站上有一些PHP代码,它从文件和echo那一行读取一行。在其中一个cade行中,我以{$varname}的形式放置了一个变量连接,但最终结果它实际上是echos {$ varname}而不是用变量切换它。

该行显示:

<p>Today's date (at the server) is {$date}.</p>

用于回显该行的代码为:

$line = fgets($posts);
echo $line;

该代码的输出为:&#39;今天的日期(在服务器上)为{$ date}。&#39;

变量$date在代码中先前声明。我想知道是否有一些特殊的方法可以为文件中的行做这个,或者我是不是这样做了?

编辑:输出也可在http://codegamecentral.grn.cc/main/?pageNumber=2获得。

另一个编辑:此代码通过while循环运行,直到它到达文件末尾,逐行读取。这应该是一个快速的解决方案,当与不包含{$date}的字符串一起使用时不会引起问题。

3 个答案:

答案 0 :(得分:3)

string_replace()怎么样?

echo str_replace('{$date}', $date, $line);

答案 1 :(得分:2)

这就是你可以做你想做的事情:

eval("\$line = \"$line\";");
echo $line; 

警告: 虽然这可以完成这项工作,但我强烈建议你不要这样做,除非你100%确定只有你或者可信赖的人才能生成将以这种方式评估的文件,因为eval()可以在里面运行任何PHP代码。变量。

答案 2 :(得分:1)

您正在以文本形式阅读一行,除非针对代码完成,否则PHP替换将无效。

您需要一些更复杂的处理(或者告诉PHP将该文本视为代码,使用eval;出于安全原因,强烈建议不要这样做,并且可能无法在任何地方使用{{1出于同样的安全原因,网站管理员有时会禁用此功能。

最强大的替代方法是使用eval识别preg_replace_callback等文本序列,并将其替换为{$varname}。当然,$varname需要定义或检查是否存在:

$varname

输出:

function expandVariables($text, $allowedVariables) {
    return preg_replace_callback('#{\$([a-z][a-z_0-9]*)}#i',
        function($replace) use ($allowedVariables) {
            if (array_key_exists($replace[1], $allowedVariables)) {
                return $allowedVariables[$replace[1]];
            }
            return "NO '{$replace[1]} VARIABLE HERE.";
        },
        $text
    );
}

$date = date('Y-m-d H:i:s');

$line = '<p>Now (at the server) is {$date}.</p>';

$vars = get_defined_vars(); // LOTS of memory :-(

// better:
// $vars = array ( 'date' => $date, ... ); // Only allowed variables.

$eval = expandVariables($line, $vars);

print "The line is {$line}\nand becomes:\n{$eval}";

注意事项

这个实现比直接The line is <p>Now (at the server) is {$date}.</p> and becomes: <p>Now (at the server) is 2014-10-12 18:36:16.</p> 更安全,它将执行在读取行中找到的所有的任何PHP代码。 它仍可用于输出任何已定义变量的内容,前提是攻击者知道其名称并允许其请求;一个公认的不切实际的例子是eval()

为了更安全,尽管以牺牲灵活性为代价,我赞同Viktor Svensson的解决方案,该解决方案只允许设置非常具体的变量,并且既简单又快捷:

<p>Hello, {$adminPassword}!</p>

此外,您可能有兴趣查看一些模板解决方案,例如Smarty

处理整个文件

要处理整个文件,如果内存不是对象,则在两种情况下(preg和str_)都可以将整个文件作为一个行数组加载:

// Remember to use 'single quotes' for '{$variables}', because you DO NOT
// want expanded them in here, but in the replaced text!

$text = str_replace(array('{$date}', '{$time}' /*, ...more... */),
                    array(date('Y-m-d'), date('H:i:s') /*, ...more... */),
                    $text);

并使用$file = file($fileName); 作为替换的主题。然后你可以迭代结果:

$file

速度

人们通常不会欣赏的是正则表达式快速。我不知道文本匹配算法// replaceVariables receives a string and returns a string // or receives an array of strings and returns the same. $text = replaceVariables($file, $variables); foreach ($text as $line) { // Do something with $line, where variables have already been replaced. } 采用了什么(我认为 Boyer-Moore's),但preg具有Perlishly数组感知的优势。它具有较重的设置(在字典大小上呈线性),但随后在更换时间内“缩放”得更好,而str_replace是常量设置,在替换时间内线性缩放。这意味着str_replace将在大规模替代中节省大量时间;在更简单的背景下,情况会更糟。

非常大致,运行时间为(S + R L V)* V(V =变量数,L =行数)其中preg_replace具有可检测性S和可忽略不计的R,而str则相反。使用较大的V值时,您确实需要最小的R,即使代价是设置时间S增加。

preg_replace

当然,可维护性也是一个问题 - Dependency on Variable N.. ? variables, 18 lines, keylen 5, vallen 20 v preg advantage 5 -82% 15 -55% 25 -2% 35 14% 45 65% 55 41% 65 51% 75 197% 85 134% 95 338% Dependency on File length. 32 variables, ? lines, keylen 5, vallen 20 l preg advantage 5 -31% 15 -33% 25 14% 35 80% 45 116% 一个代码行中执行,并且函数本身由PHP团队维护。围绕str_replace构建的函数需要多达15行。当然,经过测试,您不需要再修改它,只需将它传递给字典。

循环

最后,您可能希望使用变量引用其他变量。在这种情况下,preg和str_都不会可靠地工作,你必须实现自己的循环:

preg_replace

输出结果为:

<?php
$file   = "This is a {\$test}. And {\$another}. And {\$yet_another}.\n";

$vars   = array(
    "test"  => "test",
    "another" => "another {\$test}",
    "yet_another" => "yet {\$another} {\$test}",
);

$text = preg_replace_callback('#{\$([a-z][a-z_0-9]*)}#i',
    function($replace) use ($vars) {
        if (array_key_exists($replace[1], $vars)) {
            return $vars[$replace[1]];
        }
        return "NO '{$replace[1]} VARIABLE HERE.";
    },
    $file
);

$keys   = array_map(function($k){ return "{\${$k}}"; }, array_keys($vars));
$vals   = array_values($vars);

$text2  = str_replace($keys, $vals, $file);

$text3  = $file;
do {
    $prev   = $text3;
    $text3  = str_replace($keys, $vals, $text3);
} while ($text3 != $prev);

print "PREG: {$text}\nSTR_: {$text2}\nLOOP: {$text3}\n";