PHP Zastąpić ostatnie wystąpienie ciągu w łańcuchu?


Odpowiedzi:


228

Możesz użyć tej funkcji:

function str_lreplace($search, $replace, $subject)
{
    $pos = strrpos($subject, $search);

    if($pos !== false)
    {
        $subject = substr_replace($subject, $replace, $pos, strlen($search));
    }

    return $subject;
}

To wciąż powracało prawdą bez względu na wszystko. Rozważ zmodyfikowanie go na: if ($ pos) {$ subject = substr_replace ($ subject, $ replace, $ pos, strlen ($ search)); return $ subject; } else {return false; }
Jazzy,

4
@Jason Nie wraca TRUEbez względu na wszystko. Zwraca ciąg bez względu na wszystko. Jeśli nie można dokonać wymiany, zwraca oryginał $subject, tak jak substr_replace i str_replacezrób.
Mischa,

@Mischa Czy to nie to samo w tym przypadku? Próbowałem zrobić coś takiego jak! Str_lreplace, ale jeśli nie zwraca fałszu, jest uważane za prawdziwe, prawda? Tak czy inaczej, pomogło mi to i doceniam to. Dzięki.
Jazzy

1
Jak to działa? strpos — Find the position of the first occurrence of a substring in a string- edycja: wow. Geniusze PHP naprawdę stworzyli funkcję o nazwie strposi strrpos? Dzięki ...
BarryBones41

1
@Barry to jest jeden przypadek, w którym PHP nie zasługują winę :-) Nazwy są wzorowane na dziesiątków lat strstr, strrstrstandardowej biblioteki C, które są takie same funkcje. (Ale czy musieli zmienić nazwę?)
alexis

30

Kolejny 1-liniowy, ale bez preg:

$subject = 'bourbon, scotch, beer';
$search = ',';
$replace = ', and';

echo strrev(implode(strrev($replace), explode(strrev($search), strrev($subject), 2))); //output: bourbon, scotch, and beer

3
FWIW, przyjęte rozwiązanie jest około 35% szybsze niż to rozwiązanie.
JustCarty

27
$string = 'this is my world, not my world';
$find = 'world';
$replace = 'farm';
$result = preg_replace(strrev("/$find/"),strrev($replace),strrev($string),1);
echo strrev($result); //output: this is my world, not my farm

Moim zdaniem najfajniejsze rozwiązanie, a jednocześnie łatwe do zrozumienia.
Blackbam

Dlaczego to działa z odwróconymi wszystkimi ciągami? Czy jest jakiś (zakładam) określony wzrost wydajności podczas używania wyrażeń regularnych?
Kamafeather

Nie, to faktycznie zmniejsza wydajność, ale to dlatego, że chcesz tylko ostatniego wystąpienia, więc ograniczasz wyszukiwanie do jednego i
odwracasz

15

Poniższe, raczej zwarte rozwiązanie, używa pozytywnego asercji wyprzedzającej PCRE, aby dopasować ostatnie wystąpienie podciągu będącego przedmiotem zainteresowania, to znaczy wystąpienie podciągu, po którym nie następuje żadne inne wystąpienie tego samego podciągu. W ten sposób przykład zastępuje last 'fox'z 'dog'.

$string = 'The quick brown fox, fox, fox jumps over the lazy fox!!!';
echo preg_replace('/(fox(?!.*fox))/', 'dog', $string);

WYNIK: 

The quick brown fox, fox, fox jumps over the lazy dog!!!

5
Pomysł jest dobry, ale kod nie. To musi być:$string = 'The quick brown fox, fox, fox jumps over the lazy fox!!!'; echo preg_replace('/(fox(?!.*fox))/', 'dog', $string);
Roemer

Rzeczywiście, kod, który opublikowałem, zmienia wszystkie wystąpienia „fox” z wyjątkiem ostatniego na „pies”, ale to, czego chcemy, jest dokładnie odwrotne. Dziękuję za wskazanie, że zastąpienie? = Z?! rozwiązuje problem.
John Sonderson

11

Możesz to zrobić:

$str = 'Hello world';
$str = rtrim($str, 'world') . 'John';

Wynik to „Hello John”;

pozdrowienia


4
Działa to, o ile nie ma żadnych powtarzających się znaków. W mojej sytuacji usuwam numer strony z daty archiwizacji, więc mam „2015-12 / 2” i wszystkie / i wszystkie 2 z końca stają się „2015-1”.
Mike

Działa to tylko wtedy, gdy ostatnie wyszukiwane wystąpienie jest ostatnim słowem i nie ma po nim żadnych dodatkowych znaków.
AwesomeGuy,

To nie działa, ponieważ rtrimnie zachowuje się tak, jak myślisz. Usuwa z końca wszystkie znaki, które istnieją w ciągu wyszukiwania w dowolnej kolejności (i zawsze dołącza zastąpienie), np. „Witaj słowo” -> „Witaj John”, „Witaj panie” -> „Witaj John”, „Witaj motor "->" Hello motJohn "," Hello worldy "->" Hello worldyJohn ".
Jake,

5

To również zadziała:

function str_lreplace($search, $replace, $subject)
{
    return preg_replace('~(.*)' . preg_quote($search, '~') . '(.*?)~', '$1' . $replace . '$2', $subject, 1);
}

AKTUALIZACJA Nieco bardziej zwięzła wersja ( http://ideone.com/B8i4o ):

function str_lreplace($search, $replace, $subject)
{
    return preg_replace('~(.*)' . preg_quote($search, '~') . '~', '$1' . $replace, $subject, 1);
}

Czy robię to źle? Jeśli tak, po prostu mnie zignoruj ​​:) ||| echo str_lreplace ("x", "y", "to x lub tamto x"); => Wynik
edorian

@edorian: Ups! Przepraszam, napisałem, że w pośpiechu, poprawna wersja jest tutaj: ideone.com/vR073 .
Alix Axel

5

Tylko jedna linia kodu (późna odpowiedź, ale warto ją dodać):

$string = 'The quick brown fox jumps over the lazy dog';
$find_me = 'dog';

preg_replace('/'. $find_me .'$/', '', $string);

końcówka $ wskazuje koniec łańcucha.


5

To odwieczne pytanie, ale dlaczego wszyscy pomijają najprostsze rozwiązanie oparte na wyrażeniach regularnych? Zwykłe kwantyfikatory regexp są chciwe, ludzie! Jeśli chcesz znaleźć ostatnią instancję wzoru, po prostu trzymaj się .*przed nim. Oto jak:

$text = "The quick brown fox, fox, fox, fox, jumps over etc.";
$fixed = preg_replace("((.*)fox)", "$1DUCK", $text);
print($fixed);

Spowoduje to zamianę ostatniego wystąpienia „fox” na „DUCK”, tak jak powinno, i wypisze:

The quick brown fox, fox, fox, DUCK, jumps over etc.

1
Dzięki! Idealna funkcja do owinięcia mojej ekspresji, aby to osiągnąć. W moim przypadku ostatni przecinek zastępuję znakami „i”. Cieszę się, że przewinąłem trochę tę listę odpowiedzi.
rlhane

3
$string = "picture_0007_value";
$findChar =strrpos($string,"_");
if($findChar !== FALSE) {
  $string[$findChar]=".";
}

echo $string;

Oprócz błędów w kodzie, Faruk Unal ma najlepszą odpowiedź. Jedna funkcja załatwia sprawę.


Musisz sprawdzić, czy $ findChar nie jest fałszywe (tak samo jak w akceptowanej odpowiedzi). Jeśli ciąg nie zawiera szukanego ciągu, otrzymasz powiadomienie i pierwszy znak zostanie zastąpiony.
kudłaty

To świetnie, ale w obecnej formie może zastąpić tylko 1 znak 1 znakiem.
Pete,

3

Możesz użyć strrpos (), aby znaleźć ostatnie dopasowanie.

$string = "picture_0007_value";
$findChar =strrpos($string,"_");

$string[$findChar]=".";

echo $string;

Wyjście: picture_0007.value


2

Skrót do zaakceptowanej odpowiedzi

function str_lreplace($search, $replace, $subject){ 
    return is_numeric($pos=strrpos($subject,$search))?
    substr_replace($subject,$replace,$pos,strlen($search)):$subject;
}


0

Użyj „$” w wyrażeniu reg, aby dopasować koniec ciągu

$string = 'The quick brown fox jumps over the lazy fox';
echo preg_replace('/fox$/', 'dog', $string);

//output
'The quick brown fox jumps over the lazy dog'

4
działa to tylko wtedy, gdy ostatnie wystąpienie znajduje się na końcu łańcucha ideone.com/nbNSNq
cawecoy

1
To nie zadziała, jeśli po ostatnim „lisie” pojawią się inne postacie.
John Sonderson

0

Dla zainteresowanych: napisałem funkcję, która wykorzystuje preg_match, dzięki czemu można zastępować z prawej strony za pomocą wyrażenia regularnego.

function preg_rreplace($search, $replace, $subject) {
    preg_match_all($search, $subject, $matches, PREG_SET_ORDER);
    $lastMatch = end($matches);

    if ($lastMatch && false !== $pos = strrpos($subject, $lastMatchedStr = $lastMatch[0])) {
        $subject = substr_replace($subject, $replace, $pos, strlen($lastMatchedStr));
    }

    return $subject;
}

Lub jako skrótowe połączenie / implementacja obu opcji:

function str_rreplace($search, $replace, $subject) {
    return (false !== $pos = strrpos($subject, $search)) ?
        substr_replace($subject, $replace, $pos, strlen($search)) : $subject;
}
function preg_rreplace($search, $replace, $subject) {
    preg_match_all($search, $subject, $matches, PREG_SET_ORDER);
    return ($lastMatch = end($matches)) ? str_rreplace($lastMatch[0], $replace, $subject) : $subject;
}

na podstawie https://stackoverflow.com/a/3835653/3017716 i https://stackoverflow.com/a/23343396/3017716

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.