【问题标题】:Best way to substitute variables in plain text using PHP使用 PHP 在纯文本中替换变量的最佳方法
【发布时间】:2008-11-12 07:08:36
【问题描述】:

获取一些包含 PHP 样式变量的纯文本(不是 PHP 代码)的最佳方法是什么,然后替换为变量的值。这有点难以描述,所以这里有一个例子。

// -- myFile.txt --
Mary had a little $pet.

// -- parser.php --
$pet = "lamb";
// open myFile.txt and transform it such that...
$newContents = "Mary had a little lamb.";

我一直在考虑使用正则表达式或者eval(),尽管我不确定哪个最简单。这个脚本只会在本地运行,所以关于安全问题和eval() 的任何担忧都不适用(我认为?)

我还要补充一点,我可以使用get_defined_vars() 将所有必要的变量放入一个数组中:

$allVars = get_defined_vars();
echo $pet;             // "lamb"
echo $allVars['pet'];  // "lamb"

【问题讨论】:

    标签: php variables substitution


    【解决方案1】:

    正则表达式很简单。它不会关心 eval() 会认为语法错误的事情。

    这是查找 PHP 样式变量名称的模式。

    \$\w+
    

    我可能会采用这种通用模式并使用 PHP 数组来查找我找到的每个匹配项(使用 (preg_replace_callback())。这样正则表达式只需应用一次,从长远来看会更快.

    $allVars = get_defined_vars();
    $file = file_get_contents('myFile.txt');
    
    // unsure if you have to use single or double backslashes here for PHP to understand
    preg_replace_callback ('/\$(\w+)/', "find_replacements", $file);
    
    // replace callback function
    function find_replacements($match)
    {
      global $allVars;
      if (array_key_exists($match[1], $allVars))
        return $allVars[$match[1]];
      else
        return $match[0];
    }
    

    【讨论】:

    • 其实就是这样(来自 php 手册):[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*
    • 是的,但过于复杂。您正在寻找空白或单词边界。
    • 我知道这是一个巨大的边缘案例,我现在只是在吹毛求疵,但是 \w 不会匹配像 çäÄ 这样的重音字符,它们是有效字符。
    • 但是您提到了 PHP 样式变量名称,所以我排除了这种可能性。 :-)
    • 哦,它们是有效的 php 变量字符。请参阅此页面上的第一个代码示例:au2.php.net/manual/en/language.variables.php
    【解决方案2】:

    如果它来自可信赖的来源,您可以使用(戏剧性的停顿)eval()(观众惊恐地倒吸一口凉气)。

    $text = 'this is a $test'; // single quotes to simulate getting it from a file
    $test = 'banana';
    $text = eval('return "' . addslashes($text) . '";');
    echo $text; // this is a banana
    

    【讨论】:

    • addslashes() 是否可以消除任何可能的语法歧义?
    • @Tomalak:是的。从手册中,它替换了单引号、双引号和 NULL 字符。虽然您没有这些,但您仍然在字符串中。这是一个使用 eval 的漂亮、简单的示例;我以前做过类似的事情,当我需要破解一些东西以供一次性内部使用时。UP!
    • 嗯,当 $name 未定义时,它对 "$name" 有何反应?
    • 和普通 php 一样——它会发出一个通知(如果你有通知)并将 $name 视为一个空字符串。
    【解决方案3】:

    这是我刚刚想出的,但我仍然很想知道是否有更好的方法。干杯。

    $allVars = get_defined_vars();
    $file = file_get_contents('myFile.txt');
    
    foreach ($allVars as $var => $val) {
        $file = preg_replace("@\\$" . $var . "([^a-zA-Z_0-9\x7f-\xff]|$)@", $val . "\\1", $file);
    }
    

    【讨论】:

      【解决方案4】:

      必须是 $pet 吗?可以改为<?= $pet ?> 吗?因为如果是这样,只需使用包含。这就是 php 作为模板引擎的全部想法。

      //myFile.txt
      Mary had a little <?= $pet ?>.
      
      //parser.php
      
      $pet = "lamb";
      ob_start();
      include("myFile.txt");
      $contents = ob_end_clean();
      
      echo $contents;
      

      这会回响:

      Mary had a little lamb.
      

      【讨论】:

        【解决方案5】:

        根据具体情况,str_replace 可能会成功。

        例子:

        // -- myFile.txt --
        Mary had a little %pet%.
        
        // -- parser.php --
        $pet = "lamb";
        $fileName = myFile.txt
        
        $currentContents = file_get_contents($fileName);
        
        $newContents = str_replace('%pet%', $pet, $currentContents);
        
        // $newContents == 'Mary had a little lamb.'
        

        当您查看 str_replace 时,请注意搜索和替换参数可以使用值数组来搜索和替换。

        【讨论】:

        • 我也这么认为,但规范显示该变量由 $ 定义为起始字符,而不是由 %'s 括起来
        • 如果您使用 $var 而不是 %var%,如果您同时拥有 $abc 和 $abcdef,它将无法工作。
        【解决方案6】:

        你可以使用strtr:

        $text = file_get_contents('/path/to/myFile.txt'); // "Mary had a little $pet."
        $allVars = get_defined_vars(); // array('pet' => 'lamb');
        $translate = array();
        
        foreach ($allVars as $key => $value) {
            $translate['$' . $key] = $value; // prepend '$' to vars to match text
        }
        
        // translate is now array('$pet' => 'lamb');
        
        $text = strtr($text, $translate);
        
        echo $text; // "Mary had a little lamb."
        

        您可能希望在 get_defined_vars() 中进行前置操作,因此您不会将变量循环两次。或者更好的是,只需确保您最初分配的任何键都与您在 myFile.txt 中使用的标识符相匹配。

        【讨论】:

        • 如果有这样的东西:“$pet $petty”会起作用吗?
        • 它不适用于“$pet $petty”。但是,如果您还包括一个后缀(如“$pet$ $petty$”或类似的东西),它会。这不是 strtr 的工作方式吗?试试看,确实如此。
        猜你喜欢
        • 2011-02-19
        • 2012-07-30
        • 1970-01-01
        • 2015-10-09
        • 2014-06-17
        • 1970-01-01
        • 2013-12-26
        • 2010-10-25
        • 2010-12-31
        相关资源
        最近更新 更多