php 使用 str_replace 使其仅作用于第一个匹配项?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1252693/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using str_replace so that it only acts on the first match?
提问by Nick Heiner
I want a version of str_replace()that only replaces the first occurrence of $searchin the $subject. Is there an easy solution to this, or do I need a hacky solution?
我想的一个版本str_replace()是只替换第一次出现$search的$subject。有没有一个简单的解决方案,或者我需要一个hacky解决方案?
回答by zombat
There's no version of it, but the solution isn't hacky at all.
没有它的版本,但解决方案一点也不笨拙。
$pos = strpos($haystack, $needle);
if ($pos !== false) {
$newstring = substr_replace($haystack, $replace, $pos, strlen($needle));
}
Pretty easy, and saves the performance penalty of regular expressions.
非常简单,并节省了正则表达式的性能损失。
Bonus: If you want to replace lastoccurrence, just use strrposin place of strpos.
奖励:如果你想替换最后一次出现,只需使用strrpos代替strpos.
回答by karim79
Can be done with preg_replace:
可以用preg_replace完成:
function str_replace_first($from, $to, $content)
{
$from = '/'.preg_quote($from, '/').'/';
return preg_replace($from, $to, $content, 1);
}
echo str_replace_first('abc', '123', 'abcdef abcdef abcdef');
// outputs '123def abcdef abcdef'
The magic is in the optional fourth parameter [Limit]. From the documentation:
神奇之处在于可选的第四个参数 [Limit]。从文档:
[Limit] - The maximum possible replacements for each pattern in each subject string. Defaults to -1 (no limit).
[限制] - 每个主题字符串中每个模式的最大可能替换。默认为 -1(无限制)。
Though, see zombat's answerfor a more efficient method (roughly, 3-4x faster).
不过,请参阅zombat 的答案以了解更有效的方法(大约快 3-4 倍)。
回答by Bas
Edit: both answers have been updated and are now correct. I'll leave the answer since the function timings are still useful.
编辑:两个答案都已更新,现在是正确的。我会留下答案,因为功能计时仍然有用。
The answers by 'zombat' and 'too much php' are unfortunately not correct. This is a revision to the answer zombat posted (as I don't have enough reputation to post a comment):
不幸的是,'zombat' 和 'too much php' 的答案是不正确的。这是对 zombat 发布的答案的修订(因为我没有足够的声誉发表评论):
$pos = strpos($haystack,$needle);
if ($pos !== false) {
$newstring = substr_replace($haystack,$replace,$pos,strlen($needle));
}
Note the strlen($needle), instead of strlen($replace). Zombat's example will only work correctly if needle and replace are the same length.
注意 strlen($needle),而不是 strlen($replace)。Zombat 的示例只有在针和替换的长度相同时才能正常工作。
Here's the same functionality in a function with the same signature as PHP's own str_replace:
这是与 PHP 自己的 str_replace 具有相同签名的函数中的相同功能:
function str_replace_first($search, $replace, $subject) {
$pos = strpos($subject, $search);
if ($pos !== false) {
return substr_replace($subject, $replace, $pos, strlen($search));
}
return $subject;
}
This is the revised answer of 'too much php':
这是'太多php'的修订答案:
implode($replace, explode($search, $subject, 2));
Note the 2 at the end instead of 1. Or in function format:
注意末尾的 2 而不是 1。 或者在函数格式中:
function str_replace_first($search, $replace, $subject) {
return implode($replace, explode($search, $subject, 2));
}
I timed the two functions and the first one is twice as fast when no match is found. They are the same speed when a match is found.
我为这两个函数计时,当找不到匹配项时,第一个函数的速度是它的两倍。当找到匹配时,它们的速度相同。
回答by oLinkWebDevelopment
I wondered which one was the fastest, so I tested them all.
我想知道哪个最快,所以我测试了它们。
Below you will find:
下面你会发现:
- A comprehensive list of all the functions that have been contributed onto this page
- Benchmark testing for each contrubution (average execution time over 10,000 runs)
- Links to each answer (for the full code)
- 已贡献到此页面的所有功能的完整列表
- 每个 contrubution 的基准测试(平均执行时间超过 10,000 次运行)
- 每个答案的链接(完整代码)
All functions were tested with the same settings:
所有功能都使用相同的设置进行测试:
$string = 'OOO.OOO.OOO.S';
$search = 'OOO';
$replace = 'B';
Functions that only replace the firstoccurrence of a string within a string:
仅替换字符串中第一次出现的字符串的函数:
substr_replace($string, $replace, 0, strlen($search));[CONTRIBUTED BY] => zombat [OOO.OOO.OOO.S] => B.OOO.OOO.S [AVERAGE TIME] => 0.0000062883 [SLOWER BY] => FASTESTreplace_first($search, $replace, $string);[CONTRIBUTED BY] => too much php [OOO.OOO.OOO.S] => B.OOO.OOO.S [AVERAGE TIME] => 0.0000073902 [SLOWER BY] => 17.52%preg_replace($search, $replace, $string, 1);[CONTRIBUTED BY] => karim79 [OOO.OOO.OOO.S] => B.OOO.OOO.S [AVERAGE TIME] => 0.0000077519 [SLOWER BY] => 23.27%str_replace_once($search, $replace, $string);[CONTRIBUTED BY] => happyhardik [OOO.OOO.OOO.S] => B.OOO.OOO.S [AVERAGE TIME] => 0.0000082286 [SLOWER BY] => 30.86%str_replace_limit($search, $replace, $string, $count, 1);[CONTRIBUTED BY] => bfrohs - expanded renocor [OOO.OOO.OOO.S] => B.OOO.OOO.S [AVERAGE TIME] => 0.0000083342 [SLOWER BY] => 32.54%str_replace_limit($search, $replace, $string, 1);[CONTRIBUTED BY] => renocor [OOO.OOO.OOO.S] => B.OOO.OOO.S [AVERAGE TIME] => 0.0000093116 [SLOWER BY] => 48.08%str_replace_limit($string, $search, $replace, 1, 0);[CONTRIBUTED BY] => jayoaK [OOO.OOO.OOO.S] => B.OOO.OOO.S [AVERAGE TIME] => 0.0000093862 [SLOWER BY] => 49.26%
substr_replace($string, $replace, 0, strlen($search));[CONTRIBUTED BY] => zombat [OOO.OOO.OOO.S] => B.OOO.OOO.S [AVERAGE TIME] => 0.0000062883 [SLOWER BY] => FASTESTreplace_first($search, $replace, $string);[CONTRIBUTED BY] => too much php [OOO.OOO.OOO.S] => B.OOO.OOO.S [AVERAGE TIME] => 0.0000073902 [SLOWER BY] => 17.52%preg_replace($search, $replace, $string, 1);[CONTRIBUTED BY] => karim79 [OOO.OOO.OOO.S] => B.OOO.OOO.S [AVERAGE TIME] => 0.0000077519 [SLOWER BY] => 23.27%str_replace_once($search, $replace, $string);[CONTRIBUTED BY] => happyhardik [OOO.OOO.OOO.S] => B.OOO.OOO.S [AVERAGE TIME] => 0.0000082286 [SLOWER BY] => 30.86%str_replace_limit($search, $replace, $string, $count, 1);[CONTRIBUTED BY] => bfrohs - expanded renocor [OOO.OOO.OOO.S] => B.OOO.OOO.S [AVERAGE TIME] => 0.0000083342 [SLOWER BY] => 32.54%str_replace_limit($search, $replace, $string, 1);[CONTRIBUTED BY] => renocor [OOO.OOO.OOO.S] => B.OOO.OOO.S [AVERAGE TIME] => 0.0000093116 [SLOWER BY] => 48.08%str_replace_limit($string, $search, $replace, 1, 0);[CONTRIBUTED BY] => jayoaK [OOO.OOO.OOO.S] => B.OOO.OOO.S [AVERAGE TIME] => 0.0000093862 [SLOWER BY] => 49.26%
Functions that only replace the lastoccurrence of a string within a string:
仅替换字符串中最后一次出现的字符串的函数:
substr_replace($string, $replace, strrpos($string, $search), strlen($search));[CONTRIBUTED BY] => oLinkSoftware - modified zombat [OOO.OOO.OOO.S] => OOO.OOO.B.S [AVERAGE TIME] => 0.0000068083 [SLOWER BY] => FASTESTstrrev(implode(strrev($replace), explode(strrev($search), strrev($string), 2)));[CONTRIBUTED BY] => oLinkSoftware [OOO.OOO.OOO.S] => OOO.OOO.B.S [AVERAGE TIME] => 0.0000084460 [SLOWER BY] => 24.05%
substr_replace($string, $replace, strrpos($string, $search), strlen($search));[CONTRIBUTED BY] => oLinkSoftware - modified zombat [OOO.OOO.OOO.S] => OOO.OOO.B.S [AVERAGE TIME] => 0.0000068083 [SLOWER BY] => FASTESTstrrev(implode(strrev($replace), explode(strrev($search), strrev($string), 2)));[CONTRIBUTED BY] => oLinkSoftware [OOO.OOO.OOO.S] => OOO.OOO.B.S [AVERAGE TIME] => 0.0000084460 [SLOWER BY] => 24.05%
回答by too much php
Unfortunately, I don't know of any PHP function which can do this.
You can roll your own fairly easily like this:
不幸的是,我不知道有任何 PHP 函数可以做到这一点。
您可以像这样轻松地推出自己的产品:
function replace_first($find, $replace, $subject) {
// stolen from the comments at PHP.net/str_replace
// Splits $subject into an array of 2 items by $find,
// and then joins the array with $replace
return implode($replace, explode($find, $subject, 2));
}
回答by Parziphal
I created this littlefunction that replaces string on string (case-sensitive) with limit, without the need of Regexp. It works fine.
我创建了这个小函数,它用限制替换字符串上的字符串(区分大小写),不需要正则表达式。它工作正常。
function str_replace_limit($search, $replace, $string, $limit = 1) {
$pos = strpos($string, $search);
if ($pos === false) {
return $string;
}
$searchLen = strlen($search);
for ($i = 0; $i < $limit; $i++) {
$string = substr_replace($string, $replace, $pos, $searchLen);
$pos = strpos($string, $search);
if ($pos === false) {
break;
}
}
return $string;
}
Example usage:
用法示例:
$search = 'foo';
$replace = 'bar';
$string = 'foo wizard makes foo brew for evil foo and Hyman';
$limit = 2;
$replaced = str_replace_limit($search, $replace, $string, $limit);
echo $replaced;
// bar wizard makes bar brew for evil foo and Hyman
回答by luchaninov
function str_replace_once($search, $replace, $subject) {
$pos = strpos($subject, $search);
if ($pos === false) {
return $subject;
}
return substr($subject, 0, $pos) . $replace . substr($subject, $pos + strlen($search));
}
回答by PYK
=> CODE WAS REVISED, so consider some comments too old
=> 代码已修改,因此请考虑一些过时的评论
And thanks everyoneon helping me to improve that
Any BUG, please communicate me; I'll fix that up right after
并感谢大家帮助我改进
有BUG请私信我;我会马上解决这个问题
So, lets go for:
所以,让我们去:
Replacing the first 'o'to 'ea'for example:
例如,将第一个'o'替换为'ea':
$s='I love you';
$s=str_replace_first('o','ea',$s);
echo $s;
//output: I leave you
The function:
功能:
function str_replace_first($a,$b,$s)
{
$w=strpos($s,$a);
if($w===false)return $s;
return substr($s,0,$w).$b.substr($s,$w+strlen($a));
}
回答by Rufinus
The easiest way would be to use regular expression.
最简单的方法是使用正则表达式。
The other way is to find the position of the string with strpos() and then an substr_replace()
另一种方法是使用 strpos() 找到字符串的位置,然后使用 substr_replace()
But i would really go for the RegExp.
但我真的会选择 RegExp。
回答by zack
$string = 'this is my world, not my world';
$find = 'world';
$replace = 'farm';
$result = preg_replace("/$find/",$replace,$string,1);
echo $result;

