Souvik Ray
Souvik Ray

Reputation: 3038

Replace all except the first occurrence of a substring in Python?

I have a string which looks like below

string = "SELECT sdfdsf SELECT sdrrr SELECT 5445ff"

Now I want to replace every occurrence of SELECT except the first one with @@@SELECT so that in the end string looks like this

"SELECT sdfdsf @@@SELECT sdrrr @@@SELECT 5445ff"

Now Python replace() replaces all occurrence of SELECT.

string = string.replace("SELECT", "@@@SELECT)

So the string becomes

"@@@SELECT sdfdsf @@@SELECT sdrrr @@@SELECT 5445ff"

How do I ensure except the first instance, everything else is replaced?

Note: The string can have n occurrences of SELECT

Upvotes: 8

Views: 8793

Answers (7)

Andrei Odegov
Andrei Odegov

Reputation: 3439

One more approach:

import re
from itertools import chain, repeat
string = 'SELECT sdfdsf SELECT sdrrr SELECT 5445ff'
string = ''.join(x + s for x, s in zip(chain(['', 'S'], repeat('@@@S')), re.split(r'\bS(?=ELECT\b)', string)))
print(string)

Output:

SELECT sdfdsf @@@SELECT sdrrr @@@SELECT 5445ff

Upvotes: 1

Ajax1234
Ajax1234

Reputation: 71471

You can use itertools.count with re.sub:

import re, itertools
c = itertools.count()
string = "SELECT sdfdsf SELECT sdrrr SELECT 5445ff"
r = re.sub(r"\bSELECT\b", lambda x:x.group() if not next(c) else f'@@@{x.group()}', string)

Output:

'SELECT sdfdsf @@@SELECT sdrrr @@@SELECT 5445ff'

However, if SELECT is always placed at the start of the string, you can use a negative lookbehind:

r = re.sub('(?<!^)SELECT', lambda x:f'@@@{x.group()}', string)

Output:

'SELECT sdfdsf @@@SELECT sdrrr @@@SELECT 5445ff'

Upvotes: 4

RomanPerekhrest
RomanPerekhrest

Reputation: 92894

With additional "reversed" substitution step:

s = "SELECT sdfdsf SELECT sdrrr SELECT 5445ff"
res = s.replace("SELECT", "@@@SELECT").replace("@@@SELECT", "SELECT", 1)
print(res)

The output:

SELECT sdfdsf @@@SELECT sdrrr @@@SELECT 5445ff

A more sophisticated, but ensuring target word boundaries, could be as below:

import re

def make_replacer():
    rpl = ''
    def inner(m):
        nonlocal rpl
        res = rpl + m.group()
        rpl = '@@@'
        return res
    return inner

s = "SELECT sdfdsf SELECT sdrrr SELECT 5445ff"
res = re.sub(r'\bSELECT\b', make_replacer(), s)
print(res)   # SELECT sdfdsf @@@SELECT sdrrr @@@SELECT 5445ff

Upvotes: 10

kabanus
kabanus

Reputation: 26005

How about just skipping the first 3 letters of what you have?

string = string.replace("SELECT", "@@@SELECT)[3:]

Upvotes: 3

user12066865
user12066865

Reputation:

use this code (more simple and only use split and replace)

string = "SELECT sdfdsf SELECT sdrrr SELECT 5445ff"
string = "SELECT " + string.split('SELECT', 1)[1].strip().replace('SELECT', '@@@SELECT').strip()

But if there's a text before the SELECT, use

string = "SELECT sdfdsf SELECT sdrrr SELECT 5445ff"
string = string.split('SELECT', 1)[0].strip() + " SELECT " + string.split('SELECT', 1)[1].strip().replace('SELECT', '@@@SELECT').strip()

That code remove the first SELECT and then replace all the SELECT sub-string and then add the SELECT string to the main string

Upvotes: 0

codrelphi
codrelphi

Reputation: 1065

You can use the method partition and replace. The working code looks like:

string = "SELECT sdfdsf SELECT sdrrr SELECT 5445ff"
parts = string.partition("SELECT")  # returns a tuple
results = parts[0] + parts[1] + parts[2].replace("SELECT", "@@@SELECT")

print(results)

So you will get:

SELECT sdfdsf @@@SELECT sdrrr @@@SELECT 5445ff

If string = "Blabla is SELECT sdfdsf SELECT sdrrr SELECT 5445ff", you will get:

Blabla is SELECT sdfdsf @@@SELECT sdrrr @@@SELECT 5445ff

Upvotes: 3

unknown.prince
unknown.prince

Reputation: 752

import string

def removeExceptFirst(s, old, new):
    i = s.find(old) + len(old)
    newStr = s[0:i]
    newStr += s[i:].replace(old, new)
    return newStr

print(removeExceptFirst("SELECT sdfdsf SELECT sdrrr SELECT 5445ff", "SELECT", "@@@SELECT"))

The Output:

SELECT sdfdsf @@@SELECT sdrrr @@@SELECT 5445ff

Upvotes: 1

Related Questions