Replace nth occurrence of substring in string
我想替换字符串中第n个出现的子字符串。
一定有什么我想做的事情是
实现这一目标的最简单,最Python化的方法是什么?
为什么不重复:我不想在这种方法中使用正则表达式,而我发现的类似问题的大多数答案都只是正则表达式剥离或真正复杂的功能。 我真的想要尽可能简单而不是正则表达式的解决方案。
您可以使用带有
1 2 3 4 5 6 7 8 9 10 11 12 13 | def nth_repl(s, sub, repl, nth): find = s.find(sub) # if find is not p1 we have found at least one match for the substring i = find != -1 # loop util we find the nth or we find no match while find != -1 and i != nth: # find + 1 means we start at the last match start index + 1 find = s.find(sub, find + 1) i += 1 # if i is equal to nth we found nth matches so replace if i == nth: return s[:find]+repl+s[find + len(sub):] return s |
例:
1 2 3 4 5 6 7 8 9 10 | In [14]: s ="foobarfoofoobarbar" In [15]: nth_repl(s,"bar","replaced",3) Out[15]: 'foobarfoofoobarreplaced' In [16]: nth_repl(s,"foo","replaced",3) Out[16]: 'foobarfooreplacedbarbar' In [17]: nth_repl(s,"foo","replaced",5) Out[17]: 'foobarfoofoobarbar' |
我使用简单的函数,该函数列出所有出现的事件,选择第n个位置,并使用它将原始字符串分成两个子字符串。然后,它替换第二个子字符串中的第一个匹配项,并将子字符串连接回新的字符串中:
1 2 3 4 5 6 7 8 9 | import re def replacenth(string, sub, wanted, n) where = [m.start() for m in re.finditer(sub, string)][n-1] before = string[:where] after = string[where:] after = after.replace(sub, wanted, 1) newString = before + after print newString |
对于这些变量:
1 2 3 4 | string = 'ababababababababab' sub = 'ab' wanted = 'CD' n = 5 |
输出:
1 | ababababCDabababab |
笔记:
The
where variable actually is a list of matches' positions, where you pick up the nth one. But list item index starts with0 usually, not with1 . Therefore there is an-1 index andn variable is the actual nth substring. My example finds 5th string. If you usen index and want to find 5th position, you'll needn to be4 . Which you use usually depends on the function, which generates ourn .This should be the simplest way, but maybe it isn't the most Pythonic way, because the
where variable construction needs importingre library. Maybe somebody will find even more Pythonic way.Sources and some links in addition:
where construction: Find all occurrences of a substring in Python- string splitting: https://www.daniweb.com/programming/software-development/threads/452362/replace-nth-occurrence-of-any-sub-string-in-a-string
- similar question: Find the nth occurrence of substring in a string
我提出了以下内容,其中还考虑了替换左侧或右侧所有"旧"字符串出现的选项。自然,没有替代所有出现的选项,因为标准的str.replace可以完美地工作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | def nth_replace(string, old, new, n=1, option='only nth'): """ This function replaces occurrences of string 'old' with string 'new'. There are three types of replacement of string 'old': 1) 'only nth' replaces only nth occurrence (default). 2) 'all left' replaces nth occurrence and all occurrences to the left. 3) 'all right' replaces nth occurrence and all occurrences to the right. """ if option == 'only nth': left_join = old right_join = old elif option == 'all left': left_join = new right_join = old elif option == 'all right': left_join = old right_join = new else: print("Invalid option. Please choose from: 'only nth' (default), 'all left' or 'all right'") return None groups = string.split(old) nth_split = [left_join.join(groups[:n]), right_join.join(groups[n:])] return new.join(nth_split) |
最后一个答案几乎是完美的-只有一个更正:
1 2 3 4 5 6 7 | def replacenth(string, sub, wanted, n): where = [m.start() for m in re.finditer(sub, string)][n - 1] before = string[:where] after = string[where:] after = after.replace(sub, wanted) newString = before + after return newString |
替换后,后字符串必须再次存储在this变量中。
谢谢您的出色解决方案!
我调整了@aleskva的答案,以更好地使用正则表达式和通配符:
1 2 3 4 5 6 7 8 9 10 11 12 | import re def replacenth(string, sub, wanted, n): pattern = re.compile(sub) where = [m for m in pattern.finditer(string)][n-1] before = string[:where.start()] after = string[where.end():] newString = before + wanted + after return newString replacenth('abdsahd124njhdasjk124ndjaksnd124ndjkas', '1.*?n', '15', 1) |
这给出
我意识到这个问题明确指出他们不想使用正则表达式,但是能够以清晰的方式使用通配符可能会很有用(因此,我的回答是)。
1 2 3 4 5 6 7 | def replace_nth_occurance(some_str, original, replacement, n): """ Replace nth occurance of a string with another string """ some_str.replace(original, replacement, n) for i in range(n): some_str.replace(replacement, original, i) return some_str |
我有类似的需求,即在日志中查找IP并选择性地仅替换src IP或dst IP字段。这就是我以Python方式实现的方式;
1 2 3 4 5 6 7 | import re mystr = '203.23.48.0 DENIED 302 449 800 1.1 302 http d.flashresultats.fr 10.111.103.202 GET GET - 188.92.40.78 ' src = '1.1.1.1' replace_nth = lambda mystr, pattern, sub, n: re.sub(re.findall(pattern, mystr)[n - 1], sub, mystr) result = replace_nth(mystr, '\S*\d+\.\d+\.\d+\.\d+\S*', src, 2) print(result) |