删除特定字符后面的字符串部分

200
我在想如何在PHP中删除特定子字符串后的所有内容。
例如:
Posted On April 6th By Some Dude

我希望它能够删除包括子字符串"By"在内的所有文本

谢谢


1
如果子字符串出现两次(或更多),该怎么办? - Bart Kiers
一些相关链接展示了一系列技术,对不同的输入值具有相同的基本效果:在php中从第一个字符出现的位置删除到字符串结尾的所有内容从日期时间戳字符串中删除可选的时间组件删除特定字符后的所有字符 - mickmackusa
16个回答

381
$variable = substr($variable, 0, strpos($variable, "By"));

简单来说:给我一个字符串的部分,从开始到第一次遇到分隔符的位置结束。


18
如果“by”存在,那么只做这个怎么样? - Alisso
5
没错。如果“By”未被找到,strpos函数将返回FALSE。如果给出的长度为false,则substr函数将返回一个空字符串。在实际使用中,最好先检查是否存在“By”,只有存在时才执行此操作(否则就保持原样)。 - Austin Fitzpatrick
我提供了一个答案,我认为它解决了下面的所有问题,并且还解释了如何处理各种事情,例如不区分大小写、多个出现次数和正则表达式。如果有人想要更灵活地做任何事情或者无法控制输入,那么最好检查一下。 - azoundria
如果我想删除的字符串后面是“\n”,该怎么办?我尝试了以下代码:$skill_current = substr($skill_current, 0, strpos($skill_current, "\n"));我还尝试了 $skill_current = substr($skill_current, 0, strpos($skill_current, "\n")); - 但都没有成功。 - Kaspar L. Palgi
1
我不知道为什么这个评分如此之高。如果strpos返回false,那么substr将返回空。 - SteveExdia
显示剩余3条评论

129

如果你正在使用PHP 5.3+,可以查看strstr()函数的$before_needle标志。

$s = 'Posted On April 6th By Some Dude';
echo strstr($s, 'By', true);

81
请注意,如果字符串中未找到部分字符串,则它将返回“FALSE”。因此,解决方案可以是:echo strstr($s,'By',true) ?: $s; - kenorb
1
kenorb的注释解决方案并非万无一失。当返回的子字符串为_falsey_时,它将失败。证明:https://3v4l.org/4kYeU - mickmackusa
@mickmackusa 很好的观点。您建议采用什么方法来解决这个问题——多行检查还是有更好的单行替代方案来执行 echo strstr($s, 'By', true) === false ? $s : strstr($s, 'By', true) - Steve Chambers
1
@Steve,PHP手册明确注明strstr()不应用于检查一个字符串是否存在于另一个字符串中,出于性能原因,建议使用strpos()。尽管如此,我仍会寻求单个函数调用。选择正确的技术取决于针在干草堆中未被发现时所需的输出。我已在问题下面发布了一些链接。 - mickmackusa
1
@mickmackusa提到的strstr确实很好。虽然这里有很多答案,但我对它们没有100%的满意度,因此我根据上面的建议添加了自己的答案:https://dev59.com/G3E85IYBdhLWcg3w1HOF(请随意查看)。 - Steve Chambers
这个答案最好的部分是@kenorb的评论,揭示了我不知道的?:的用法。非常有启发。谢谢。 - undefined

52

使用explode如何:

$input = 'Posted On April 6th By Some Dude';
$result = explode(' By',$input);
return $result[0];

优点:


@bkac - 老式的方式只要能够运行并且没有过时,有什么问题吗? - squarecandy
6
这样可以避免原答案中需要额外检查分隔符字符串是否存在的步骤。 - user3657941
在字符串中不需要对所有的 By 子字符串进行拆分,因此 explode() 调用应该包含一个 2 的限制参数。使用 explode() 的缺点是,在隔离所需字符串的过程中,需要生成一个临时数组。 - mickmackusa
关于添加限制参数的观点很好。如果您处理的是一个相当可预测的数据集,比如在示例中始终是“{日期}发布,作者为{name}”,那么这并不太重要。但是,是的,添加一个限制为2是一个很好的健全检查。如果作者名字是“Byron Byronson”或其他什么,它也会使作者名仍然可以在$result[1]中使用。就生成不必要的数组而言,我认为速度和代码可读性与使用基于正则表达式的函数相比是值得的。 - squarecandy

28

你可以这样做:

$posted = preg_replace('/ By.*/', '', $posted);
echo $posted;

这是一个正则表达式替换函数,它查找字面字符串“By”及其后的任意数量字符(.*),并将它们替换为空字符串(''),结果存储在同一变量($posted)中进行搜索。

如果输入字符串中没有[空格]By,则字符串保持不变。


16

一种方法是:

$str = 'Posted On April 6th By Some Dude';
echo strtok($str, 'By'); // Posted On April 6th

这是最好的答案,即使“By”不在字符串中也可以工作。子字符串的答案是错误的,因为“by”不存在,它会失败。 - neoteknic
1
这是不正确的:该函数不会按By拆分,而是按第二个参数中的任何字符拆分。也就是说,它将按By拆分。从技术上讲,它并没有获取By之前的所有内容。 - msb
1
注意:strtok将返回字符串中字符后面的部分,如果它是字符串中的第一个字符,例如,strtok('a:b', ':')将返回a,但strtok(':b', ':')将返回b,而不是你期望的空字符串。 - Quinn Comendant

12

试试这个。

function strip_after_string($str,$char)
    {
        $pos=strpos($str,$char);    
        if ($pos!==false) 
        {
            //$char was found, so return everything up to it.
            return substr($str,0,$pos);
        } 
        else 
        {
            //this will return the original string if $char is not found.  if you wish to return a blank string when not found, just change $str to ''
            return $str; 
        }
    }

用法:

<?php
    //returns Apples
    $clean_string= strip_after_string ("Apples, Oranges, Banannas",",");
?>

6
的回答适用于你的示例情况。更一般地,当你要在不同字符串之间拆分子字符串时,建议使用正则表达式函数

$variable = preg_replace('/By.*/', '', $variable);

4
您可以使用 listexplode 函数:
list($result) = explode("By", "Posted On April 6th By Some Dude", 2);
// $result is "Posted On April 6th "

4

preg_replace提供了一种方法:

$newText = preg_replace('/\bBy\b.*$/', '', $text);

'\b'匹配单词边界(它是零宽度的,匹配单词和非单词字符之间),确保它只匹配完整的单词。虽然目标单词在示例中不作为任何其他单词的一部分出现,但通常情况下,目标可能会作为另一个单词的一部分出现(例如,在“巴比伦重访”中,“by”在F·斯科特·菲茨杰拉德的“巴比伦重访”或伯克利·布瑞思的“布鲁姆县巴比伦”中)。
'.*$'匹配到末尾的所有文本。'$'匹配字符串的末尾,并且虽然不是严格必要的,但记录了正则表达式的意图(因为正则表达式以变得难以阅读而闻名)。
正则表达式匹配从字符串开头开始,因此这将替换从第一次匹配开始的内容。如何才能匹配并替换最后一个,请参见“如何使用preg_replace仅替换字符串的最后一个匹配项?

一些关于该模式的解释以及为什么它是一个好主意会使这个答案对研究人员更有帮助。也许可以解释一下为什么这个答案比本页面上发布的其他技术更优秀。 - mickmackusa

4
$var = "Posted On April 6th By Some Dude";
$new_var = substr($var, 0, strpos($var, " By"));

这个未经解释的答案与被接受的答案存在相同的漏洞,因为没有明确的 === false 检查。当找不到针时,整个字符串被截断。我希望看到整个输入字符串,但我得到了一个零长度的字符串。https://3v4l.org/f7ue2 - mickmackusa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接