替换字符串中的占位符变量

时间:2013-04-02 20:05:40

标签: php preg-match

刚刚完成此功能。基本上,假设查看字符串并尝试查找任何占位符变量,这些变量将位于两个大括号{}之间。它抓取大括号之间的值,并使用它来查看应与键匹配的数组。然后它用匹配键数组中的值替换字符串中的大括号变量。

虽然有一些问题。首先是当它var_dump($matches)时,它将结果放入数组中的数组中。所以我必须使用两个foreach()才能获得正确的数据。

我也觉得它很沉重,我一直在寻找它,试图让它变得更好,但我有点难过。我错过了任何优化?

function dynStr($str,$vars) {
    preg_match_all("/\{[A-Z0-9_]+\}+/", $str, $matches);
    foreach($matches as $match_group) {
        foreach($match_group as $match) {
            $match = str_replace("}", "", $match);
            $match = str_replace("{", "", $match);
            $match = strtolower($match);
            $allowed = array_keys($vars);
            $match_up = strtoupper($match);
            $str = (in_array($match, $allowed)) ? str_replace("{".$match_up."}", $vars[$match], $str) : str_replace("{".$match_up."}", '', $str);
        }
    }
    return $str;
}

$variables = array("first_name"=>"John","last_name"=>"Smith","status"=>"won");
$string = 'Dear {FIRST_NAME} {LAST_NAME}, we wanted to tell you that you {STATUS} the competition.';
echo dynStr($string,$variables);
//Would output: 'Dear John Smith, we wanted to tell you that you won the competition.'

6 个答案:

答案 0 :(得分:31)

我认为,对于这么简单的任务,您不需要使用RegEx:

$variables = array("first_name"=>"John","last_name"=>"Smith","status"=>"won");
$string = 'Dear {FIRST_NAME} {LAST_NAME}, we wanted to tell you that you {STATUS} the competition.';

foreach($variables as $key => $value){
    $string = str_replace('{'.strtoupper($key).'}', $value, $string);
}

echo $string; // Dear John Smith, we wanted to tell you that you won the competition.

答案 1 :(得分:11)

我希望我参加聚会还为时不晚 - 我就是这样做的:

function template_substitution($template, $data) {
    $placeholders = array_keys($data);
    foreach ($placeholders as &$placeholder) {
        $placeholder = strtoupper("{{$placeholder}}");
    }
    return str_replace($placeholders, array_values($data), $template);
}

$variables = array(
    'first_name' => 'John',
    'last_name' => 'Smith',
    'status' => 'won',
);

$string = 'Dear {FIRST_NAME} {LAST_NAME}, we wanted to tell you that you have {STATUS} the competition.';

echo template_substitution($string, $variables);

而且,如果你有任何机会可以让你的$variables密钥与你的占位符完全匹配,那么解决方案变得非常简单:

$variables = array(
    '{FIRST_NAME}' => 'John',
    '{LAST_NAME}' => 'Smith',
    '{STATUS}' => 'won',
);

$string = 'Dear {FIRST_NAME} {LAST_NAME}, we wanted to tell you that you have {STATUS} the competition.';

echo strtr($string, $variables);

(参见PHP手册中的strtr()。)

考虑到PHP语言的本质,我相信这种方法应该会产生本线程中列出的所有内容的最佳性能。

答案 2 :(得分:6)

我认为你可以大大简化你的代码(除非我误解了一些要求):

$allowed = array("first_name"=>"John","last_name"=>"Smith","status"=>"won");

$resultString = preg_replace_callback(

    // the pattern, no need to escape curly brackets
    // uses a group (the parentheses) that will be captured in $matches[ 1 ]
    '/{([A-Z0-9_]+)}/',

    // the callback, uses $allowed array of possible variables
    function( $matches ) use ( $allowed )
    {
        $key = strtolower( $matches[ 1 ] );
        // return the complete match (captures in $matches[ 0 ]) if no allowed value is found
        return array_key_exists( $key, $allowed ) ? $allowed[ $key ] : $matches[ 0 ];
    },

    // the input string
    $yourString
);

PS。:如果要删除输入字符串中不允许的占位符,请替换

return array_key_exists( $key, $allowed ) ? $allowed[ $key ] : $matches[ 0 ];

return array_key_exists( $key, $allowed ) ? $allowed[ $key ] : '';

答案 3 :(得分:3)

这是我使用的功能:

function searchAndReplace($search, $replace){
    preg_match_all("/\{(.+?)\}/", $search, $matches);

    if (isset($matches[1]) && count($matches[1]) > 0){
        foreach ($matches[1] as $key => $value) {
            if (array_key_exists($value, $replace)){
                $search = preg_replace("/\{$value\}/", $replace[$value], $search);
            }
        }
    }
    return $search;
}


$array = array(
'FIRST_NAME' => 'John',
'LAST_NAME' => 'Smith',
'STATUS' => 'won'
);

$paragraph = 'Dear {FIRST_NAME} {LAST_NAME}, we wanted to tell you that you {STATUS} the competition.';

// outputs: Dear John Smith, we wanted to tell you that you won the competition.

只需传递一些文字进行搜索,然后传递一个包含替换项的数组。

答案 4 :(得分:3)

对于登陆此页面的未来人员而言:只需要使用str循环和/或foreach方法的所有答案(包括接受的答案)都可以替代好的&#39 ; Johnny {STATUS} 的姓名为str_replace

体面的Dabbler Johnny won方法和U-D13的第二个选项(但不是第一个)是目前发布的唯一选项我认为不容易受此影响,但是由于我没有足够的声誉来添加评论,我只会写出一个完全不同的答案。

如果您的替换值包含用户输入,则更安全的解决方案是使用preg_replace_callback函数而不是strtr来避免重新替换可能显示在您的值中的任何占位符。

str_replace

输出:$string = 'Dear {FIRST_NAME} {LAST_NAME}, we wanted to tell you that you {STATUS} the competition.'; $variables = array( "first_name"=>"John", // Note the value here "last_name"=>"{STATUS}", "status"=>"won" ); // bonus one-liner for transforming the placeholders // but it's ugly enough I broke it up into multiple lines anyway :) $replacement = array_combine( array_map(function($k) { return '{'.strtoupper($k).'}'; }, array_keys($variables)), array_values($variables) ); echo strtr($string, $replacement); 而str_replace输出:Dear John {STATUS}, we wanted to tell you that you won the competition.

答案 5 :(得分:1)

/**
   replace placeholders with object
**/
$user = new stdClass();
$user->first_name = 'Nick';
$user->last_name = 'Trom';

$message = 'This is a {{first_name}} of a user. The user\'s {{first_name}} is replaced as well as the user\'s {{last_name}}.';

preg_match_all('/{{([0-9A-Za-z_]+)}}/', $message, $matches);

foreach($matches[1] as $match)
{
    if(isset($user->$match))
        $rep = $user->$match;
    else
        $rep = '';

    $message = str_replace('{{'.$match.'}}', $rep, $message);
}

echo $message;