我想要str_replace()的一个版本,它只替换$subject中第一次出现的$search。有一个简单的解决方案,还是我需要一个hack的解决方案?


当前回答

可以用preg_replace完成:

function str_replace_first($search, $replace, $subject)
{
    $search = '/'.preg_quote($search, '/').'/';
    return preg_replace($search, $replace, $subject, 1);
}

echo str_replace_first('abc', '123', 'abcdef abcdef abcdef'); 
// outputs '123def abcdef abcdef'

神奇之处在于可选的第四个参数[Limit]。从文档中可以看到:

[极限]-最大可能 每个中的每个模式的替换 主题字符串。默认为-1 (no 限制)。

不过,请参阅zombat的回答以获得更有效的方法(大约快3-4倍)。

其他回答

$str = "Hello there folks!"
$str_ex = explode("there, $str, 2);   //explodes $string just twice
                                      //outputs: array ("Hello ", " folks")
$str_final = implode("", $str_ex);    // glues above array together
                                      // outputs: str("Hello  folks")

还有一个额外的空间,但这并不重要,因为它是背景脚本在我的情况下。

编辑:两个答案都已更新,现在是正确的。我将把答案留下,因为函数时间仍然是有用的。

“僵尸”和“太多php”的答案很不幸是不正确的。这是对僵尸发布的答案的修正(因为我没有足够的声誉来发表评论):

$pos = strpos($haystack,$needle);
if ($pos !== false) {
    $newstring = substr_replace($haystack,$replace,$pos,strlen($needle));
}

注意strlen($needle),而不是strlen($replace)。Zombat的例子只有在针头和替代物长度相同的情况下才能正确工作。

下面是与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;
}

这是修改后的“too much php”的答案:

implode($replace, explode($search, $subject, 2));

注意最后的2而不是1。或函数格式:

function str_replace_first($search, $replace, $subject) {
    return implode($replace, explode($search, $subject, 2));
}

我对这两个函数进行了计时,当没有找到匹配时,第一个函数的速度是原来的两倍。当找到匹配时,它们的速度是一样的。

不幸的是,我不知道任何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));
}

根据我的测试结果,我想投票给karim79提供的regular_express。(我现在没有足够的声誉去投票!)

僵尸的解决方案使用了太多的函数调用,我甚至简化了代码。我使用PHP 5.4运行这两个解决方案10万次,结果如下:

$str = 'Hello abc, have a nice day abc! abc!';
$pos = strpos($str, 'abc');
$str = substr_replace($str, '123', $pos, 3);

1.85秒

$str = 'Hello abc, have a nice day abc! abc!';
$str = preg_replace('/abc/', '123', $str, 1);

1.35秒

如你所见。preg_replace的性能并不像很多人想象的那么差。所以如果你的常规快递不是很复杂的话,我建议你用一个漂亮的解决方案。

=> CODE已被修订,所以考虑一些太旧的注释

感谢大家帮助我改进这一点 有任何BUG,请与我沟通;我马上就去做

那么,让我们开始:

将第一个o替换为ea,例如:

$s='I love you';
$s=str_replace_first('o','ea',$s);
echo $s;

//output: I leave you

功能:

function str_replace_first($this,$that,$s)
{
    $w=strpos($s,$this);
    if($w===false)return $s;
    return substr($s,0,$w).$that.substr($s,$w+strlen($this));
}