我想用一个名为该字符串的数组中随机选择的项替换方括号([]
)中的所有字符串。
它与this issue非常相似,但有一点麻烦,因为我想用名为的数组中的字符串替换不同的括号内容。
一个例子应该让这一点更清晰。
所以说我有字符串
"This is a very [adjective] [noun], and this is a [adjective] [noun]."
变量:
$adjective = array("big","small","good","bad");
$noun = array("house","dog","car");
我们希望它通过随机选择返回"This is a very big house, and this is a good dog."
或其他任何东西。也就是说,我想编写一个PHP函数,它将用名为[string]
的数组中随机选择的项替换每个$string
。现在,如果通过随机选择它最终重复选择并不重要,但它必须为每个[]
项目做出新的选择。
我希望我已经清楚地解释了这一点。如果你得到了我想要达到的目标,并想到一个更好的方法,我会非常感激。
答案 0 :(得分:8)
(\[.*?\])
$string = "This is a very [adjective] [noun], and this is a [adjective] [noun].";
$adjective = array("big","small","good","bad");
$noun = array("house","dog","car");
// find matches against the regex and replaces them the callback function.
$result = preg_replace_callback(
// Matches parts to be replaced: '[adjective]', '[noun]'
'/(\[.*?\])/',
// Callback function. Use 'use()' or define arrays as 'global'
function($matches) use ($adjective, $noun) {
// Remove square brackets from the match
// then use it as variable name
$array = ${trim($matches[1],"[]")};
// Pick an item from the related array whichever.
return $array[array_rand($array)];
},
// Input string to search in.
$string
);
print $result;
preg_replace_callback 函数执行正则表达式搜索并使用提供的回调函数替换。
第一个参数是要匹配的正则表达式(包含在斜杠之间):/(\[.*?\])/
第二个参数是为每个匹配调用的回调函数。将当前匹配作为参数。
我们必须在这里使用use()
从函数内部访问数组,或者将数组定义为global:global $adjective = ...
。也就是说,我们必须做以下其中一项:
a)将数组定义为global
:
... global $adjective = array("big","small","good","bad"); global $noun = array("house","dog","car"); ... function($matches) { ...
b)使用use
:
... $adjective = array("big","small","good","bad"); $noun = array("house","dog","car"); ... function($matches) use ($adjective, $noun) { ...
回调函数的第一行:
修剪:使用[]
功能从匹配中移除方括号(trim
)。
$ {} :创建一个变量,用作匹配名称的数组名称。例如,如果$match
为[noun]
,则trim($matches[1],"[]")
返回noun
(不带括号),${noun}
成为数组名称:$noun
。有关该主题的更多信息,请参阅 variable variables 。
第二行随机选择$array
可用的索引号,然后返回此位置的元素。
第三个参数是输入字符串。
答案 1 :(得分:1)
以下代码将完成工作:
$string = "This is a very [adjective] [noun], and this is a [adjective] [noun]."
function replace_word ( $matches )
{
$replaces = array(
'[adjective]' => array("big", "small", "good", "bad"),
'[noun]' => array("house", "dog", "car")
);
return $replaces[$matches[0]][array_rand($replaces[ $matches[0] ])];
}
echo preg_replace_callback("(\[.*?\])", "replace_word", $string);
首先,我们在单词的[something]
部分进行正则表达式匹配,然后使用preg_replace_callback()
调用replace_word()
回调函数。此函数内部定义了一个内部$replaces
二维深度数组,每行以[word type] => array('rep1', 'rep2', ...)
格式定义。
棘手且有点混淆的行是return $replaces[$matches[0]][array_rand($replaces[ $matches[0] ])];
。如果我把它缩小一点,它对你来说会更容易解析:
$random = array_rand( $replaces[ $matches[0] ] );
$matches[0]
是单词类型,这是我们要搜索的$replaces
数组中的键。这是通过原始字符串中的正则表达式找到的。 array_rand()
基本上选择数组的一个元素,并返回其数字索引。所以$random
现在是介于0
和包含替换的数组的(number of elements - 1)
之间的整数。
return $replaces[ $matches[0] ][$random];
这将从replace数组返回$random
个元素。在代码片段中,这两行被放在一行中。
如果你想要分离元素(没有两个形容词或名词重复两次),那么你需要做另一个技巧。我们将$replaces
数组设置为不在replace_word()
函数内部,而是在其外部。
$GLOBALS['replaces'] = array(
'[adjective]' => array("big", "small", "good", "bad"),
'[noun]' => array("house", "dog", "car")
);
在函数内部,我们将本地$replaces
变量设置为对新设置数组的引用,并调用$replaces = &$GLOBALS['replaces'];
。 (&
运算符将其设置为引用,因此我们对$replaces
所做的一切(例如删除和添加元素)也会修改原始数组。没有它,它会只是副本。)
在到达return
行之前,我们会在当前要返回的密钥上调用unset()
。
unset($replaces[$matches[0]][array_rand($replaces[ $matches[0] ])]);
现在放在一起的功能如下:
function replace_word ( $matches )
{
$replaces = &$GLOBALS['replaces'];
unset($replaces[$matches[0]][array_rand($replaces[ $matches[0] ])]);
return $replaces[$matches[0]][array_rand($replaces[ $matches[0] ])];
}
由于$replaces
是对全局的引用,unset()
也会更新原始数组。 replace_word()
的下一次调用将不会再次找到相同的替换。
包含比替换值更多的替换变量的字符串将抛出未定义索引 E_NOTICE
。以下字符串不起作用:
$string = "This is a very [adjective] [noun], and this is a [adjective] [noun]. This is also an [adjective] [noun] with an [adjective] [noun].";
其中一个输出如下所示,表明我们已经用完了可能的替换:
这是一个非常大的房子,这是一个大房子。这也是一个很小的。
答案 2 :(得分:1)
这样做的另一个好(更容易)的方法(不是我的解决方案)
https://stackoverflow.com/a/15773754/2183699
使用foreach检查要替换的变量并用
替换它们str_replace();
答案 3 :(得分:0)
您可以使用preg_match和str_replace函数来实现此目标。
答案 4 :(得分:0)
这是我对mmdemirbas上面回答的小改动。它允许你在函数之外设置变量(即使用全局变量,如上所述)。
$result = preg_replace_callback(
// Matches parts to be replaced: '[adjective]', '[noun]'
'/(\[.*?\])/',
// Callback function. Use 'use()' or define arrays as 'global'
function($matches) use ($adjective, $noun) {
// Remove square brackets from the match
// then use it as variable name
$arrayname = trim($matches[1],"[]");
$array = $GLOBALS[$arrayname];
// Pick an item from the related array whichever.
return $array[array_rand($array)];
},
// Input string to search in.
$string
);
print $result;