【问题标题】:Remove a part of a string, but only when it is at the end of the string删除字符串的一部分,但仅当它位于字符串的末尾时
【发布时间】:2023-03-27 04:03:01
【问题描述】:

我需要删除一个字符串的子字符串,但前提是它位于字符串的末尾。

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

"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,但如何?

【问题讨论】:

标签: php string replace preg-replace


【解决方案1】:

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

$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:]] 字符类呢?
  • 如果存在的话,这不会删除“字符串”之前的空格。您也可以只在最后 6 个字符上使用子字符串,将它们与“字符串”进行比较,如果匹配,则将它们子字符串化。它会比 Regex 快得多。
  • 这不应该是公认的答案。将 preg_replace 用于此任务非常丑陋,逻辑错误,并且完全浪费了服务器能量/时间/周期(是的,这很重要,因为 10000000 个其他用户的网页使用 preg_replace 而不是 substr,所以您需要支付更多的托管费用)
【解决方案2】:

如果子字符串有特殊字符,使用正则表达式可能会失败。

以下内容适用于任何字符串:

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

【讨论】:

  • 最后一位可以简单地被$str = substr($str, 0, -strlen($substring)); 推荐为正则表达式的好选择。我对我的问题提出了相同的答案。如果符合我的目的,我会随时在preg_*family 上使用纯字符串函数
  • 一个简单而智能的解决方案,无需使用正则表达式即可解决所谓的简单问题。谢谢
  • 有人说“如果你的解决方案需要正则表达式,那么现在你有两个问题”。因此,为了好玩,我想为非正则表达式解决这个问题,在看到你的答案之前,我已经有了这个和@Sudhi 的评论。我不知道的一点是您可以放置​​“-”来否定而不是乘以-1。所以谢谢。
  • 请注意:应使用 mb_* 函数以确保特殊字符(例如:áéã 等)的安全
【解决方案3】:

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

/**
 * @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;
}

【讨论】:

    【解决方案4】:

    我想您可以使用regular expression,它会匹配string,然后是字符串结尾,再加上preg_replace() 函数。


    像这样的东西应该可以正常工作:

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


    备注:

    • string 匹配...好吧...string
    • 和$ 表示字符串结束

    有关更多信息,您可以阅读 PHP 手册的Pattern Syntax 部分。

    【讨论】:

      【解决方案5】:

      preg_replace 和这个模式:/string\z/i

      \z 表示字符串结束

      http://tr.php.net/preg_replace

      【讨论】:

        【解决方案6】:

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

        $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 "
        

        【讨论】:

          【解决方案7】:

          @Skrol29 的答案是最好的,但这里是函数形式并使用三元运算符:

          if (!function_exists('str_ends_with')) {
              function str_ends_with($haystack, $suffix) {
                  $length = strlen( $suffix );
                  if( !$length ) {
                      return true;
                  }
                  return substr( $haystack, -$length ) === $suffix;
              }
          }
          
          if (!function_exists('remove_suffix')) {
              function remove_suffix ($string, $suffix) {
                  return str_ends_with($string, $suffix) ? substr($string, 0, strlen($string) - strlen($suffix)) : $string;
              }
          }
          

          【讨论】:

            【解决方案8】:

            您可以使用rtrim()。

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

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

            【讨论】:

            • 虽然这适用于某些情况,但请注意 PHP trim() 函数将删除第二个参数中提供的任何字符组合。 rtrim('teststring', 'string') 返回字符串“te”,not“test”,因为“test”末尾的“st”由第二个参数中字符集的一部分字符组成到rtrim()。
            • 这确实具有误导性,可能会导致隐藏的错误。这不是一个解决方案……它只是碰巧有一个符合某些条件的副作用。
            • 也许您可以执行echo str_replace( '#', 'string', rtrim( str_replace( 'string', '#', 'this is a test string' ), '#' ) ); 之类的操作,以便仅获取特定字符串而不是组合。当然:您的字符串不必包含字符 '#' 即可工作,这绝对不是一个优雅的解决方案。
            猜你喜欢
            • 1970-01-01
            • 2020-09-03
            • 1970-01-01
            • 1970-01-01
            • 2011-03-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-02-02
            相关资源
            最近更新 更多