删除字符串的一部分,但仅当它在字符串的末尾时


76

我需要删除字符串的子字符串,但仅当它在字符串的结尾时才需要。

例如,删除以下字符串末尾的“字符串”:

"this is a test string" ->  "this is a test "
"this string is a test string" - > "this string is a test "
"this string is a test" -> "this string is a test"

有任何想法吗 ?可能是某种preg_replace,但是如何?


您可以从此独立库中找到s($str)->replaceSuffix('string')有用的信息。
caw

Answers:


119

您会注意到该$字符的使用,它表示字符串的结尾:

$new_str = preg_replace('/string$/', '', $str);

如果字符串是用户提供的变量,则最好先运行它preg_quote

$remove = $_GET['remove']; // or whatever the case may be
$new_str = preg_replace('/'. preg_quote($remove, '/') . '$/', '', $str);

preg_quote / preg_replace也可以与非ASCII(例如UTF-8)字符串一起使用吗?即说preg_*功能族知道编码吗?什么[^[:alnum:]]字符类?
Sudhi 2011年

1
如果存在,这不会删除“字符串”之前的空格。您也可以只在最后6个字符上使用子字符串,将它们与“字符串”进行比较,如果匹配,则将它们子字符串化。它比Regex快得多。
科尔·约翰逊

1
这不应是公认的答案。为这个任务使用preg_replace真是丑陋,逻辑上是错误的,并且完全浪费了服务器能量/时间/周期(是的,很重要,您要为主机支付更多的钱,因为其他用户的10000000个网页使用了preg_replace而不是substr)
FrancescoMM

26

如果子字符串包含特殊字符,则使用regexp可能会失败。

以下将适用于任何字符串:

$substring = 'string';
$str = "this string is a test string";
if (substr($str,-strlen($substring))===$substring) $str = substr($str, 0, strlen($str)-strlen($substring));

13
最后一点可以简单地$str = substr($str, 0, -strlen($substring));推荐为正则表达式的好选择。我为我的问题想出了相同的答案。preg_*如果
可以满足

2
一个简单而又智能的解决方案,可以解决所谓的简单问题,而无需使用正则表达式。谢谢
alds 2015年

1
有人说“如果您的解决方案需要正则表达式,那么现在有两个问题”。因此,为了获得乐趣,我想为非正则表达式解决此问题,在看到您的答案之前,我已经提供了这个和@Sudhi的评论。我没有意识到的一点是,您可以将“-”取反,而不是乘以-1。那谢谢啦。
ChronoFish

1
只需注意:应该使用mb_ *函数来安全处理特殊字符(例如áéã等)
Mario Cesar

10

我为字符串的左右修剪编写了这两个函数:

/**
 * @param string    $str           Original string
 * @param string    $needle        String to trim from the end of $str
 * @param bool|true $caseSensitive Perform case sensitive matching, defaults to true
 * @return string Trimmed string
 */
function rightTrim($str, $needle, $caseSensitive = true)
{
    $strPosFunction = $caseSensitive ? "strpos" : "stripos";
    if ($strPosFunction($str, $needle, strlen($str) - strlen($needle)) !== false) {
        $str = substr($str, 0, -strlen($needle));
    }
    return $str;
}

/**
 * @param string    $str           Original string
 * @param string    $needle        String to trim from the beginning of $str
 * @param bool|true $caseSensitive Perform case sensitive matching, defaults to true
 * @return string Trimmed string
 */
function leftTrim($str, $needle, $caseSensitive = true)
{
    $strPosFunction = $caseSensitive ? "strpos" : "stripos";
    if ($strPosFunction($str, $needle) === 0) {
        $str = substr($str, strlen($needle));
    }
    return $str;
}

7

我想你可以使用正则表达式,这将匹配string,然后,字符串的结束,再加上preg_replace()功能。


这样的事情应该可以正常工作:

$str = "this is a test string";
$new_str = preg_replace('/string$/', '', $str);


注意事项:

  • string 火柴...好... string
  • $表示字符串的结尾

有关更多信息,您可以阅读PHP手册的“模式语法”部分。



0

如果您不关心性能,并且只能将字符串的一部分放在字符串的末尾,那么您可以这样做:

$string = "this is a test string";
$part = "string";
$string = implode( $part, array_slice( explode( $part, $string ), 0, -1 ) );
echo $string;
// OUTPUT: "this is a test "

-4

您可以使用rtrim()

php > echo rtrim('this is a test string', 'string');
this is a test 

这仅在某些情况下有效,因为'string'只是字符掩码和字符顺序将不被遵守。


3
尽管这在某些情况下可行,但请注意,PHPtrim()函数将删除第二个参数中提供的任何字符组合rtrim('teststring', 'string')返回字符串“ te”,而不是“ test”,因为“ test”末尾的“ st”由属于to的第二个参数的字符集中的字符组成rtrim()
Cy Rossignol

1
这确实具有误导性,并可能导致潜在的错误。这不是解决方案...它恰好具有与某些条件匹配的副作用。
ChronoFish

也许您可以做一些类似的事情echo str_replace( '#', 'string', rtrim( str_replace( 'string', '#', 'this is a test string' ), '#' ) );以仅获取特定的字符串而不是组合。当然:您的字符串不必包含字符“#”即可工作,而且绝对不是一种优雅的解决方案。
Marco Panichi
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.