Python中如何替换除第一次出现的子字符串以外的所有子字符串?

8

我有一个字符串,看起来像这样

string = "SELECT sdfdsf SELECT sdrrr SELECT 5445ff"

现在,我想将每个SELECT的出现替换为@@@SELECT,除了第一个外,最终字符串应该如下所示

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

现在Python的replace()会替换所有出现的SELECT。
string = string.replace("SELECT", "@@@SELECT)

所以字符串变成:
"@@@SELECT sdfdsf @@@SELECT sdrrr @@@SELECT 5445ff"

我如何确保除了第一个实例之外,其他所有实例都被替换?
注意:该字符串可以有n个SELECT出现。
7个回答

10

使用额外的“反转”替换步骤:

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

输出结果:

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

一个更加复杂的方式,但可以确保目标词边界的方法如下:
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

4
你可以使用 itertools.countre.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)

输出:

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

然而,如果SELECT总是放在字符串开头,您可以使用负回顾后断言:
r = re.sub('(?<!^)SELECT', lambda x:f'@@@{x.group()}', string)

输出:

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

3
您可以使用方法 partitionreplace。工作代码如下:
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)

所以您将得到:

选择 sdfdsf @@@选择 sdrrr @@@选择 5445ff

如果 string = "Blabla is SELECT sdfdsf SELECT sdrrr SELECT 5445ff",则您将得到:

Blabla 是选择 sdfdsf @@@选择 sdrrr @@@选择 5445ff


3

你可以考虑跳过你已经有的前三个字母怎么样?

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

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

输出结果:

选择 sdfdsf @@@选择 sdrrr @@@选择 5445ff


1
另一种方法:

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)

输出:

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

0

使用这段代码(更简单,只使用splitreplace

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

但如果在SELECT之前有文本,请使用

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()

这段代码会移除第一个 SELECT,然后替换所有的 SELECT 子字符串,并将 SELECT 字符串添加到主字符串中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接