可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
What's the best way to take some plain text (not PHP code) which contains PHP-style variables, and then substitute in the value of the variable. This is kinda hard to describe, so here's an example.
// -- 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.";
I've been considering using a regex or perhaps eval()
, though I'm not sure which would be easiest. This script is only going to be running locally, so any worries regarding security issues and eval()
do not apply (i think?).
I'll also just add that I can get all the necessary variables into an array by using get_defined_vars()
:
$allVars = get_defined_vars();
echo $pet; // "lamb"
echo $allVars['pet']; // "lamb"
回答1:
If it's from a trusted source you can use (dramatic pause) eval() (gasps of horror from the audience).
$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
回答2:
Regex would be easy enough. And it would not care about things that eval()
would consider a syntax error.
Here's the pattern to find PHP style variable names.
\$\w+
I would probably take this general pattern and use a PHP array to look up each match I've found (using (preg_replace_callback()
). That way the regex needs to be applied only once, which is faster on the long run.
$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];
}
回答3:
Here's what I've just come up with, but I'd still be interested to know if there's a better way. Cheers.
$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:
Does it have to be $pet? Could it be <?= $pet ?>
instead? Because if so, just use include. This is the whole idea of php as a templating engine.
//myFile.txt
Mary had a little <?= $pet ?>.
//parser.php
$pet = "lamb";
ob_start();
include("myFile.txt");
$contents = ob_end_clean();
echo $contents;
This will echo out :
Mary had a little lamb.
回答5:
Depending on the situation, str_replace might do the trick.
Example:
// -- 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.'
When you look at str_replace note that search and replace parameters can take arrays of values to search for and replace.
回答6:
You could use 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."
You probably want to do the prepending in get_defined_vars(), so you don't loop the variables twice. Or better yet, just make sure whatever keys you assign initially match the identifier you use in myFile.txt.