因此,这个字符串是这样的:
"bla bla bla {VARIABLE} bla bla"
当我在函数中使用此字符串时,我希望将{VARIABLE}替换为$variable(或任何用{}字符包装的大写字符串)。$variable(和任何其他变量)将在该函数内定义。
我能做到这点吗?
因此,这个字符串是这样的:
"bla bla bla {VARIABLE} bla bla"
$TEST = 'one';
$THING = 'two';
$str = "this is {TEST} a {THING} to test";
$result = preg_replace('/\{([A-Z]+)\}/e', "$$1", $str);
使用正则表达式查找所有替换项,然后迭代结果并进行替换。确保只允许曝露想要的变量。
// white list of variables
$allowed_variables = array("test", "variable", "not_POST", "not_GET",);
preg_match("#(\{([A-Z]+?)\}#", $text, $matches);
// not sure the result is in [1], do a var_dump
while($matches[1] as $variable) {
$variable = strtolower($variable);
// only allow white listed variables
if(!in_array($variable, $allowed_variables)) continue;
$text = str_replace("{".$match."}", $$match, $text);
}
使用$$vars
和$GLOBALS
都会带来安全风险。用户应该能够明确地定义可接受的标签列表。
以下是我能想到的最简单的通用单函数解决方案。我选择使用双括号作为标记分隔符,但你可以很容易地进行修改。
/**
* replace_tags replaces tags in the source string with data from the vars map.
* The tags are identified by being wrapped in '{{' and '}}' i.e. '{{tag}}'.
* If a tag value is not present in the tags map, it is replaced with an empty
* string
* @param string $string A string containing 1 or more tags wrapped in '{{}}'
* @param array $tags A map of key-value pairs used to replace tags
* @param force_lower if true, converts matching tags in string via strtolower()
* before checking the tags map.
* @return string The resulting string with all tags replaced.
*/
function replace_tags($string, $tags, $force_lower = false)
{
return preg_replace_callback('/\\{\\{([^{}]+)\}\\}/',
function($matches) use ($force_lower, $tags)
{
$key = $force_lower ? strtolower($matches[1]) : $matches[1];
return array_key_exists($key, $tags)
? $tags[$key]
: '';
}
, $string);
}
[编辑] 增加了force_lower
参数
[编辑] 在use
列表中添加了force_lower
变量 - 感谢启动被拒绝的编辑的人。
在其他答案(特别是Bill Karwin和bouke)的基础上,我们继续探讨...
class CurlyVariables {
private static $_matchable = array();
private static $_caseInsensitive = true;
private static function var_match($matches)
{
$match = $matches[1];
if (self::$_caseInsensitive) {
$match = strtolower($match);
}
if (isset(self::$_matchable[$match]) && !is_array(self::$_matchable[$match])) {
return self::$_matchable[$match];
}
return '';
}
public static function Replace($needles, $haystack, $caseInsensitive = true) {
if (is_array($needles)) {
self::$_matchable = $needles;
}
if ($caseInsensitive) {
self::$_caseInsensitive = true;
self::$_matchable = array_change_key_case(self::$_matchable);
}
else {
self::$_caseInsensitive = false;
}
$out = preg_replace_callback("/{(\w+)}/", array(__CLASS__, 'var_match'), $haystack);
self::$_matchable = array();
return $out;
}
}
Example:
echo CurlyVariables::Replace(array('this' => 'joe', 'that' => 'home'), '{This} goes {that}', true);
这将有效……
$FOO = 'Salt';
$BAR = 'Peppa';
$string = '{FOO} and {BAR}';
echo preg_replace( '/\{([A-Z]+)\}/e', "$$1", $string );
但这似乎是个可怕的想法。
$data_bas = 'I am a {tag} {tag} {club} {anothertag} fan.'; // Tests
$vars = array(
'{club}' => 'Barcelona',
'{tag}' => 'sometext',
'{anothertag}' => 'someothertext'
);
echo strtr($data_bas, $vars);
以下是另一种解决方案,但我同意其他人对于你是否应该这样做持怀疑态度。
<?php
$string = "bla bla bla {VARIABLE} bla bla";
$VARIABLE = "foo";
function var_repl($matches)
{
return $GLOBALS[$matches[1]];
}
echo preg_replace_callback("/{(\w+)}/", "var_repl", $string);
我很高兴找到了Bill Criswell的解决方案,但是是否也可以替换这样的变量:
string tmp = "{myClass.myVar}";
其中PHP代码可能是这样的:
class myClass
{
public static $myVar = "some value";
}