I want to replace characters at the end of a python string. I have this string:

 s = "123123"

I want to replace the last 2 with x. Suppose there is a method called replace_last:

 r = replace_last(s, '2', 'x')
 print r
 1231x3

Is there any built-in or easy method to do this?

This is exactly what the rpartition function is used for:

rpartition(…)
S.rpartition(sep) -> (head, sep, tail)

Search for the separator sep in S, starting at the end of S, and return
the part before it, the separator itself, and the part after it.  If the
separator is not found, return two empty strings and S.

I wrote this function showing how to use rpartition in your use case:

def replace_last(source_string, replace_what, replace_with):
    head, _sep, tail = source_string.rpartition(replace_what)
    return head + replace_with + tail

s = "123123"
r = replace_last(s, '2', 'x')
print r

Output:

1231x3

Using regular expression function re.sub to replace words at end of string

import re
s = "123123"
s = re.sub('23$', 'penguins', s)
print s

Prints:

1231penguins

or

import re
s = "123123"
s = re.sub('^12', 'penguins', s)
print s

Prints:

penguins3123

This is one of the few string functions that doesn’t have a left and right version, but we can mimic the behaviour using some of the string functions that do.

>>> s="123123"
>>> t = s.rsplit('2', 1)
>>> u = 'x'.join(t)
>>> u
'1231x3'

or

>>> 'x'.join('123123'.rsplit('2', 1))
'1231x3'

>>> s = "aaa bbb aaa bbb"
>>> s[::-1].replace('bbb','xxx',1)[::-1]
'aaa bbb aaa xxx'

For your second example

>>> s = "123123"
>>> s[::-1].replace('2','x',1)[::-1]
'1231x3'

When the wanted match is at the end of string, re.sub comes to the rescue.

>>> import re
>>> s = "aaa bbb aaa bbb"
>>> s
'aaa bbb aaa bbb'
>>> re.sub('bbb$', 'xxx', s)
'aaa bbb aaa xxx'
>>> 

Here is a solution based on a simplistic interpretation of your question. A better answer will require more information.

>>> s = "aaa bbb aaa bbb"
>>> separator = " "
>>> parts = s.split(separator)
>>> separator.join(parts[:-1] + ["xxx"])
'aaa bbb aaa xxx'

Update

(After seeing edited question) another very specific answer.

>>> s = "123123"
>>> separator = "2"
>>> parts = s.split(separator)
>>> separator.join(parts[:-1]) + "x" + parts[-1]
'1231x3'

Update 2

There is far better way to do this. Courtesy @mizipzor.

There is a very easy way to do this, follow my steps

str = "stay am stay am  delete am"
#  want to remove the last am
str = str[:str.rfind('am')]
print(str)

Here at first, we find the index number of am‘s last occurrence, then take 0th index to that particular index.

txt = "123123"
txt = txt[::-1]
txt = txt.replace("2", "*", 1)
txt = txt[::-1]

I got a tricky answer, but it is not efficient enough


    >>> fname="12345.png.pngasdfg.png"
    >>> suffix = '.png'
    >>> fname_rev = fname[::-1]
    >>> suffix_rev = suffix[::-1]
    >>> fullname_rev = fname_rev.replace(suffix_rev, '', 1)
    >>> fullname = fullname_rev[::-1]
    >>> fullname '12345.png.pngasdfg'

Built-in function replace() takes three arguments
str.replace(old, new, max_time)
So you can delete the last mached string from the origional string

For the second example, I would recommend rsplit, as it is very simple to use and and directly achieves the goal. Here is a little function with it:

def replace_ending(sentence, old, new):
    if sentence.endswith(old):
        i = sentence.rsplit(old,1)
        new_sentence =new.join(i)
        return new_sentence
    return sentence

print(replace_ending("aaa bbb aaa bbb", "bbb", "xxx")) 

Output:

aaa bbb aaa xxx

There is a way to handle function replace to make is work backwards.
The idea is to read the string, text to replace and new text from end to start. The logic stays the same.

This is based on the way to switch a string backwards using [::-1].

For example:

>>> a = "123 456 123 456 123 456"
>>> print(a)
123 456 123 456 123 456

and we want to replace the last one, (or two, or n) occurrences of “123” with “abc”

>>> res = a[::-1].replace("123"[::-1], "abc"[::-1], 1)[::-1]
>>> print(res)
123 456 123 456 abc 456

This could be put as a function that behaves exactly like replace.

def replace_right(text, old, new, count=-1):
    """
    Return a copy with all occurrences of substring old replaced by new starting from right.
    """
    return text[::-1].replace(old[::-1], new[::-1], count)[::-1]

Execution:

>>> replace_right(a, "123", "abc", 1)
'123 456 123 456 abc 456'

>>> replace_right(a, "123", "abc", 2)
'123 456 abc 456 abc 456'