Видаліть частину рядка, але лише тоді, коли вона знаходиться в кінці рядка


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

Відповіді:


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:]]класу персонажів?
Судхі

1
Це не видаляє пробіл перед "рядком", якщо він повинен існувати. Ви також можете просто використовувати підрядок на останніх 6 символах, порівняти їх із "рядком", а якщо це збіг, підрядити їх. Це було б набагато швидше, ніж Regex.
Коул Джонсон,

1
Це не повинно бути прийнятою відповіддю. Використання preg_replace для цього завдання є потворним, неправдою в логіці та загальною втратою енергії / часу / циклів сервера (так, це важливо, ви платите своєму хостингу більше, оскільки 10000000 веб-сторінок інших користувачів використовують preg_replace замість substr)
FrancescoMM

26

Використання регулярного виразу може не вдатися, якщо підрядок має спеціальні символи.

Наступне буде працювати з будь-якими рядками:

$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
просте та розумне рішення нібито простої задачі без використання регулярних виразів. спасибі
олдс

1
Як кажуть деякі "якщо ваше рішення вимагає регулярного виразу, тепер у вас дві проблеми". Тож для задоволення я хотів вирішити цю проблему для нерегулярних виразів, і я прийшов саме з цим та коментарем @ Sudhi, перш ніж побачити вашу відповідь. Маленький фрагмент, про який я не знав, - це те, що ви можете поставити "-", щоб заперечити, а не множити на -1. Тож спасибі.
ChronoFish 29.03.18

1
Тільки примітка: слід використовувати функції mb_ *, щоб бути безпечними для спеціальних символів (наприклад: áéã тощо)
Маріо Сезар

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
Хоча це працює в деяких випадках, зауважте, що функції PHP trim()видаляють будь-яку комбінацію символів, надану у другому аргументі. rtrim('teststring', 'string')повертає рядок "te", а не "test", оскільки "st" в кінці "test" складається з символів, які є частиною набору символів у другому аргументі rtrim().
Сай Россіньоль,

1
Це справді вводить в оману і призведе до можливих прихованих помилок. Це не рішення ... це просто має побічний ефект, який відповідає деяким умовам.
ChronoFish 29.03.18

Можливо, ви можете зробити щось на зразок echo str_replace( '#', 'string', rtrim( str_replace( 'string', '#', 'this is a test string' ), '#' ) );того, щоб отримати лише конкретний рядок, а не комбінацію. Звичайно: ваш рядок не повинен містити символ "#", щоб працювати, і це, безумовно, не елегантне рішення.
Марко Панічі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.