Entfernen Sie einen Teil einer Zeichenfolge, jedoch nur, wenn er sich am Ende der Zeichenfolge befindet


75

Ich muss einen Teilstring eines Strings entfernen, aber nur, wenn er sich am ENDE des Strings befindet.

Entfernen Sie beispielsweise 'string' am Ende der folgenden Strings:

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

Irgendwelche Ideen ? Wahrscheinlich eine Art preg_replace, aber wie?


Möglicherweise finden Sie s($str)->replaceSuffix('string')hilfreiche Informationen in dieser eigenständigen Bibliothek .
Caw

Antworten:


118

Sie werden die Verwendung des $Zeichens bemerken , das das Ende einer Zeichenfolge kennzeichnet:

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

Wenn es sich bei der Zeichenfolge um eine vom Benutzer bereitgestellte Variable handelt, sollten Sie sie preg_quotezuerst ausführen :

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

Funktioniert preg_quote / preg_replace auch mit Nicht-ASCII-Zeichenfolgen (z. B. UTF-8)? dh zu sagen, sind preg_*Funktionsfamilien der Codierung bewusst? Was ist mit der [^[:alnum:]]Charakterklasse?
Sudhi

1
Dadurch wird das Leerzeichen vor "string" nicht entfernt, wenn es vorhanden wäre. Sie können auch nur Teilzeichenfolgen für die letzten 6 Zeichen verwenden, sie mit "Zeichenfolge" vergleichen und sie, wenn es eine Übereinstimmung ist, Teilzeichenfolgen ausgeben. Es wäre viel schneller als Regex.
Cole Johnson

Dies sollte nicht die akzeptierte Antwort sein. Die Verwendung von preg_replace für diese Aufgabe ist höllisch hässlich, logisch falsch und eine totale Verschwendung von Serverenergie / -zeit / -zyklen (ja, es ist wichtig, dass Sie Ihr Hosting mehr bezahlen, da 10000000 Webseiten anderer Benutzer preg_replace anstelle von substr verwenden).
FrancescoMM

25

Die Verwendung von regulärem Ausdruck kann fehlschlagen, wenn der Teilstring Sonderzeichen enthält.

Folgendes funktioniert mit beliebigen Zeichenfolgen:

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

13
Das letzte Bit kann einfach $str = substr($str, 0, -strlen($substring));als gute Alternative für Regex hochgestuft werden. Ich habe die gleiche Antwort für mein Problem gefunden. Ich würde preg_*jederzeit reine String-Funktionen über Familien verwenden, wenn dies meinen Zweck erfüllt
Sudhi

1
Eine einfache und intelligente Lösung für ein vermeintlich einfaches Problem ohne Verwendung regulärer Ausdrücke. danke
alds

Wie einige sagen "Wenn Ihre Lösung Regex erfordert, haben Sie jetzt zwei Probleme". Zum Spaß wollte ich dieses Problem für Nicht-Regex lösen und war genau mit diesem und @ Sudhis Kommentar gekommen, bevor ich Ihre Antwort sah. Das kleine Stück, das mir nicht bewusst war, war, dass Sie "-" setzen können, um zu negieren, anstatt mit -1 zu multiplizieren. So danke.
ChronoFish

1
Nur eine Anmerkung: sollte mb_ * -Funktionen verwenden, um für spezielle Zeichen sicher zu sein (z. B. áéã usw.)
Mario Cesar

10

Ich habe diese beiden Funktionen für den linken und rechten Schnitt eines Strings geschrieben:

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

Ich nehme an, Sie könnten einen regulären Ausdruck verwenden , der mit der Funktion übereinstimmt stringund dann das Ende der Zeichenfolge koppelt preg_replace().


So etwas sollte gut funktionieren:

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


Anmerkungen :

  • string Streichhölzer ... na ja ... string
  • und $bedeutet Ende der Zeichenfolge

Weitere Informationen finden Sie im Abschnitt Pattern Syntax des PHP-Handbuchs.



0

Wenn Ihnen die Leistung nichts ausmacht UND der Teil der Zeichenfolge nur am Ende der Zeichenfolge platziert werden kann, können Sie Folgendes tun:

$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

Sie können rtrim () verwenden .

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

Dies funktioniert nur in einigen Fällen, da 'string'nur eine Zeichenmaske und die Zeichenreihenfolge nicht eingehalten werden.


3
Beachten Sie, dass die PHP- trim()Funktionen in einigen Fällen alle im zweiten Argument angegebenen Zeichenkombinationen entfernen . rtrim('teststring', 'string')Gibt die Zeichenfolge "te" zurück, nicht "test", da das "st" am Ende von "test" aus Zeichen besteht, die Teil des Zeichensatzes im zweiten Argument von sind rtrim().
Cy Rossignol

1
Dies ist wirklich irreführend und führt zu möglicherweise versteckten Fehlern. Es ist keine Lösung ... es hat nur einen Nebeneffekt, der einigen Bedingungen entspricht.
ChronoFish

Vielleicht können Sie so etwas tun echo str_replace( '#', 'string', rtrim( str_replace( 'string', '#', 'this is a test string' ), '#' ) );, um nur die bestimmte Zeichenfolge und keine Kombination zu erhalten. Natürlich: Ihre Zeichenfolge muss nicht das Zeichen '#' enthalten, um zu funktionieren, und es ist definitiv keine elegante Lösung.
Marco Panichi
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.