使用str_replace使它只对第一个匹配起作用?

Nic*_*ner 303 php string

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

zom*_*bat 562

没有它的版本,但解决方案根本不是hacky.

$pos = strpos($haystack, $needle);
if ($pos !== false) {
    $newstring = substr_replace($haystack, $replace, $pos, strlen($needle));
}
Run Code Online (Sandbox Code Playgroud)

非常简单,并且可以节省正则表达式的性能损失.


额外奖励:如果您想要替换最后一次出现,只需使用strrpos代替strpos.

  • 可以更快,并且将使用比正则表达式更少的内存.不知道为什么会有人投票...... (17认同)
  • 我喜欢这种方法,但代码有错误,substr_replace调用的最后一个参数应该是strlen($ needle)而不是strlen($ replace)..请注意! (12认同)
  • 我不同意@CamiloMartin关于行数和错误可能性的问题.虽然`substr_replace`是一个有点难以使用的函数,因为所有的参数,真正的问题是用数字进行字符串操作有时只是_tricky_ - 你必须小心将正确的变量/偏移量传递给函数.我实际上甚至说上面的代码是最直接的,对我来说,逻辑上的方法. (9认同)
  • 从某种意义上说,它是“hacky”的,因为它需要花费相当多的时间来弄清楚发生了什么。此外,如果它是清晰的代码,就不会提到该代码有错误。如果有可能在这么小的片段中犯错误,那就太hacky了。 (2认同)

kar*_*m79 321

可以用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'
Run Code Online (Sandbox Code Playgroud)

神奇的是可选的第四个参数[Limit].从文档:

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


但是,请参阅zombat的答案,以获得更有效的方法(大约快3-4倍).

  • 这种方法的缺点是正则表达式的性能损失. (38认同)
  • 由于令人讨厌的逃避问题,这作为通用解决方案失败. (32认同)
  • 另一个缺点是你必须在"needle"上使用preg_quote()并在替换中转义元字符$和\. (27认同)
  • 正常表达式由于"性能"而被解雇,如果性能是主要关注点,我们就不会编写PHP!除了'/'之外的东西可以用来包装模式,也许'〜',这将有助于在某种程度上避免逃逸问题.这取决于数据是什么,它来自何处. (2认同)

Bas*_*Bas 94

编辑:两个答案都已更新,现在是正确的.我会留下答案,因为功能时间仍然有用.

遗憾的是,'zombat'和'太多php'的答案都不正确.这是对zombat发布的答案的修订(因为我没有足够的声誉来发表评论):

$pos = strpos($haystack,$needle);
if ($pos !== false) {
    $newstring = substr_replace($haystack,$replace,$pos,strlen($needle));
}
Run Code Online (Sandbox Code Playgroud)

请注意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;
}
Run Code Online (Sandbox Code Playgroud)

这是"太多PHP"的修订答案:

implode($replace, explode($search, $subject, 2));
Run Code Online (Sandbox Code Playgroud)

注意结尾2而不是1.或者在函数格式中:

function str_replace_first($search, $replace, $subject) {
    return implode($replace, explode($search, $subject, 2));
}
Run Code Online (Sandbox Code Playgroud)

我将两个函数计时,第一个函数在没有找到匹配时快两倍.找到匹配时速度相同.

  • @Andrew [`stripos()`](http://php.net/manual/en/function.stripos.php)来救援:-) (4认同)

oLi*_*ent 72

我想知道哪一个是最快的,所以我测试了它们.

您将在下面找到:

  • 已提供到此页面的所有功能的完整列表
  • 每个控制的基准测试(平均执行时间超过10,000次)
  • 每个答案的链接(完整代码)

所有功能都使用相同的设置进行测试:

$string = 'OOO.OOO.OOO.S';
$search = 'OOO'; 
$replace = 'B';
Run Code Online (Sandbox Code Playgroud)

仅替换字符串中第一次出现的字符串的函数:


仅替换字符串中最后一次出现的字符串的函数:


too*_*php 54

不幸的是,我不知道任何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));
}
Run Code Online (Sandbox Code Playgroud)


Par*_*hal 7

我创建了这个函数,用字符串(区分大小写)替换字符串,不需要Regexp.它工作正常.

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;
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

$search  = 'foo';
$replace = 'bar';
$string  = 'foo wizard makes foo brew for evil foo and jack';
$limit   = 2;

$replaced = str_replace_limit($search, $replace, $string, $limit);

echo $replaced;
// bar wizard makes bar brew for evil foo and jack
Run Code Online (Sandbox Code Playgroud)


小智 6

$str = "/property/details&id=202&test=123#tab-6p";
$position = strpos($str,"&");
echo substr_replace($str,"?",$position,1);
Run Code Online (Sandbox Code Playgroud)

使用 substr_replace 我们可以仅替换字符串中第一个字符的出现。as & 重复多次,但仅在第一个位置我们必须将 & 替换为 ?


PYK*_*PYK 5

=> 代码已修订,因此请考虑一些注释太旧

感谢大家帮助我改进这一点

有任何BUG请联系我;我会立即解决这个问题

那么,让我们继续:

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

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

//output: I leave you
Run Code Online (Sandbox Code Playgroud)

功能:

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));
}
Run Code Online (Sandbox Code Playgroud)