【发布时间】:2011-09-29 14:35:35
【问题描述】:
如果你有字符串
'Old string Old more string Old some more string'
你想得到
'New1 string New2 more string New3 some more string'
你会怎么做?
换句话说,您需要用变量字符串 'New'.$i 替换所有 'Old' 实例。怎么办?
【问题讨论】:
如果你有字符串
'Old string Old more string Old some more string'
你想得到
'New1 string New2 more string New3 some more string'
你会怎么做?
换句话说,您需要用变量字符串 'New'.$i 替换所有 'Old' 实例。怎么办?
【问题讨论】:
来自str_replace 上的 PHP 手册:
用替换字符串替换所有出现的搜索字符串
mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )搜索
正在搜索的值,也称为 needle。一个数组可以用来指定多个针。
替换
替换找到的搜索值的替换值。一个数组可以用来指定多个替换。
主题
被搜索和替换的字符串或数组,也称为 haystack。
如果subject是一个数组,则对subject的每一项进行查找替换,返回值也是一个数组。
计数
如果通过,这将设置为执行的替换次数。
【讨论】:
str_replace 确实接受了多个替换参数。
$search应该被不同的$replace替换。根据问题:它将始终用相同的字符串替换每次出现的Old。
$count = 0;
$str = preg_replace_callback(
'~Old~',
create_function('$matches', 'return "New".$count++;'),
$str
);
【讨论】:
$count。
不需要正则表达式的迭代解决方案:
$str = 'Old string Old more string Old some more string';
$old = 'Old';
$new = 'New';
$i = 1;
$tmpOldStrLength = strlen($old);
while (($offset = strpos($str, $old, $offset)) !== false) {
$str = substr_replace($str, $new . ($i++), $offset, $tmpOldStrLength);
}
strpos() 中的$offset 只是一点点微优化。我不知道是否值得(事实上我什至不知道,如果它改变了什么),但我们的想法是我们不需要在已经处理的子字符串中搜索$old。
见Demo
Old string Old more string Old some more string
New1 string New2 more string New3 some more string
【讨论】:
strpos() 中的 $offset 是可选的。因为$old从左到右替换strpos()总是返回$old最左边出现的索引,每次替换都会向前移动。这里的$offset 应该避免,我们在字符串的部分中寻找$old,不能 再包含$old。
用途:
$str = 'Old string Old more string Old some more string';
$i = 1;
while (preg_match('/Old/', $str)) {
$str = preg_replace('/Old/', 'New'.$i++, $str, 1);
}
echo $str,"\n";
输出:
New1 string New2 more string New3 some more string
【讨论】:
我有一些类似的解决方案,例如 KingCrunch's,但正如他已经回答的那样,我想知道带有替换回调的 str_replace 变体并想出了这个 (Demo):
$subject = array('OldOldOld', 'Old string Old more string Old some more string');
$search = array('Old', 'string');
$replace = array(
function($found, $count) {return 'New'.$count;},
function($found, $count) {static $c=0; return 'String'.(++$c);}
);
$replace = array();
print_r(str_ureplace($search, $replace, $subject));
/**
* str_ureplace
*
* str_replace like function with callback
*
* @param string|array search
* @param callback|array $replace
* @param string|array $subject
* @param int $replace_count
* @return string|array subject with replaces, FALSE on error.
*/
function str_ureplace($search, $replace, $subject, &$replace_count = null) {
$replace_count = 0;
// Validate input
$search = array_values((array) $search);
$searchCount = count($search);
if (!$searchCount) {
return $subject;
}
foreach($search as &$v) {
$v = (string) $v;
}
unset($v);
$replaceSingle = is_callable($replace);
$replace = $replaceSingle ? array($replace) : array_values((array) $replace);
foreach($replace as $index=>$callback) {
if (!is_callable($callback)) {
throw new Exception(sprintf('Unable to use %s (#%d) as a callback', gettype($callback), $index));
}
}
// Search and replace
$subjectIsString = is_string($subject);
$subject = (array) $subject;
foreach($subject as &$haystack) {
if (!is_string($haystack)) continue;
foreach($search as $key => $needle) {
if (!$len = strlen($needle))
continue;
$replaceSingle && $key = 0;
$pos = 0;
while(false !== $pos = strpos($haystack, $needle, $pos)) {
$replaceWith = isset($replace[$key]) ? call_user_func($replace[$key], $needle, ++$replace_count) : '';
$haystack = substr_replace($haystack, $replaceWith, $pos, $len);
}
}
}
unset($haystack);
return $subjectIsString ? reset($subject) : $subject;
}
【讨论】:
$search是一个字符串,还是一个数组:codepad.org/H4MZCiLd 不过,我觉得可能有用。