【问题标题】:Remove a string from the beginning of a string从字符串的开头删除一个字符串
【发布时间】:2010-12-23 08:40:40
【问题描述】:

我有一个如下所示的字符串:

$str = "bla_string_bla_bla_bla";

如何删除第一个bla_;但只有在字符串的开头找到它?

使用str_replace(),它会删除所有 bla_'s。

【问题讨论】:

标签: php string


【解决方案1】:

简单的形式,没有正则表达式:

$prefix = 'bla_';
$str = 'bla_string_bla_bla_bla';

if (substr($str, 0, strlen($prefix)) == $prefix) {
    $str = substr($str, strlen($prefix));
} 

耗时:0.0369 毫秒(0.000,036,954 秒)

还有:

$prefix = 'bla_';
$str = 'bla_string_bla_bla_bla';
$str = preg_replace('/^' . preg_quote($prefix, '/') . '/', '', $str);

耗时:0.1749 毫秒(0.000,174,999 秒)第一次运行(编译),之后0.0510 毫秒(0.000,051,021 秒)。

显然是在我的服务器上配置的。

【讨论】:

  • 我从未见过三元运算符被滥用得如此严重,一个简单的if(condition) { statement } 会更清晰。
  • @salathe,我不明白。提出了惯用的和基于正则表达式的解决方案:在效率方面比较两者有助于找到最佳(再次在效率方面)答案。为什么这么邪恶?
  • @cbrandolino,没有人说它是邪恶的。我只是认为这与问题完全无关;就像“这里有两个解决方案,这里有一些小猫的照片以获得更多支持”。
  • @salathe 小猫根本不相关,分析(勉强)是。他甚至没有根据他的分析来衡量答案,只是客观地添加了它。 话虽如此,给出两个相同的答案,一个有小猫,一个没有; 我会投票给小猫,谁不会?:P
  • if (substr($str, 0, strlen($prefix)) == $prefix) 可以更改为 if (0 === strpos($str, $prefix)) 以避免不必要的内存分配,同时保持相同的可读性:)
【解决方案2】:

您可以使用带有插入符号 (^) 的正则表达式,它将匹配锚定到字符串的开头:

$str = preg_replace('/^bla_/', '', $str);

【讨论】:

  • 我想知道它是否比substr() 版本更快...我猜是这样,并且应该标记为正确答案。
  • 除非它必须是preg_quote'd
  • 我认为这对程序员的眼睛来说不那么痛苦,而且更直观。即使它在性能上输给了另一个建议的解决方案(我真的很怀疑),我仍然更喜欢这个。
  • multibyte nightmare 是其他解决方案的另一个问题,但如果文件的编码正确,则此方法效果很好。无论如何,它不应该在这个问题的范围内,所以我不在乎。
  • 回过头来说,这还有一个额外的好处,那就是使用主题字符串数组。 substrstrpos 不能接受数组。你去吧,如果你正在处理一个数组,一个明确的性能提升。干杯!
【解决方案3】:
function remove_prefix($text, $prefix) {
    if(0 === strpos($text, $prefix))
        $text = substr($text, strlen($prefix)).'';
    return $text;
}

【讨论】:

  • 不需要.''
  • 对于它的价值,因为每个人似乎都在这里进行了微优化,据我计算,这个始终是最快的。 100 万次迭代出现在 0.17 秒,而接受的答案中的 (substr($str, 0, strlen($prefix)) == $prefix) 更像是 0.37
【解决方案4】:

这里。

$array = explode("_", $string);
if($array[0] == "bla") array_shift($array);
$string = implode("_", $array);

【讨论】:

  • 测量 0.0000459153 秒 :)
  • 不错的速度,但这是硬编码的,取决于以_ 结尾的指针。有通用版吗?
  • 我不会使用explode(),但如果你必须,那么你应该使用它的limit参数。此答案缺少教育解释。
【解决方案5】:

这是一种更快的方法:

// strpos is faster than an unnecessary substr() and is built just for that 
if (strpos($str, $prefix) === 0) $str = substr($str, strlen($prefix));

【讨论】:

    【解决方案6】:

    速度不错,但这是硬编码的,取决于以 _ 结尾的指针。有通用版吗? – toddmo 6 月 29 日 23:26

    一般版本:

    $parts = explode($start, $full, 2);
    if ($parts[0] === '') {
        $end = $parts[1];
    } else {
        $fail = true;
    }
    

    一些基准测试:

    <?php
    
    $iters = 100000;
    $start = "/aaaaaaa/bbbbbbbbbb";
    $full = "/aaaaaaa/bbbbbbbbbb/cccccccccc/dddddddddd/eeeeeeeeee";
    $end = '';
    
    $fail = false;
    
    $t0 = microtime(true);
    for ($i = 0; $i < $iters; $i++) {
        if (strpos($full, $start) === 0) {
            $end = substr($full, strlen($start));
        } else {
            $fail = true;
        }
    }
    $t = microtime(true) - $t0;
    printf("%16s : %f s\n", "strpos+strlen", $t);
    
    $t0 = microtime(true);
    for ($i = 0; $i < $iters; $i++) {
        $parts = explode($start, $full, 2);
        if ($parts[0] === '') {
            $end = $parts[1];
        } else {
            $fail = true;
        }
    }
    $t = microtime(true) - $t0;
    printf("%16s : %f s\n", "explode", $t);
    

    在我相当旧的家用电脑上:

    $ php bench.php
    

    输出:

       strpos+strlen : 0.158388 s
             explode : 0.126772 s
    

    【讨论】:

      【解决方案7】:

      我认为 substr_replace 可以满足您的需求,您可以将替换限制为字符串的一部分: http://nl3.php.net/manual/en/function.substr-replace.php(这将使您只能查看字符串的开头。)

      你可以使用 str_replace 的 count 参数(http://nl3.php.net/manual/en/function.str-replace.php),这将允许你限制替换的数量,从左边开始,但它不会强制它在开头。

      【讨论】:

      • substr_replace 将替换给定范围内的字符,无论它们是您要删除的前缀还是其他内容。 OP 想要删除 bla_ “只有在字符串的开头找到它时”。
      • 这个答案具有误导性和低价值。如果您只是想删除链接,您可以在问题下提供评论。 str_replace() 的计数参数不允许您限制替换次数。
      猜你喜欢
      • 2015-01-28
      • 2015-02-03
      • 1970-01-01
      • 1970-01-01
      • 2016-06-24
      • 1970-01-01
      • 1970-01-01
      • 2011-04-08
      • 2019-11-15
      相关资源
      最近更新 更多