Лучший способ заменить все вхождения символа в строке после первого вхождения

#python #python-3.x

Вопрос:

В настоящее время я занимаюсь этим:

 teststring = "abc-def-ghi-jkl"
pos = teststring.find('-')
newstr = "{}-{}".format(teststring[0:pos], teststring[pos   1:].replace('-', '_'))
 

Это кажется излишне неуклюжим. Есть ли более питонический способ сделать это?

Комментарии:

1. Не уверен, что это будет улучшением, но вы можете использовать .split вместо .find, например, a,b = teststring.split('-', 1) тогда вам не придется выполнять все эти нарезки.

Ответ №1:

Вы можете использовать str.split :

 pre, post = teststring.split('-', 1)
newstr = pre   '-'   post.replace('-', '_')
 

Как и ваше оригинальное решение, это работает только в том случае, если в строке есть хотя бы один - . Вы можете использовать распаковку аргументов переменной длины, чтобы исправить это:

 *pre, post = 'asdfd--saf'.split('-', 1)
newstr = '-'.join(pre   [post.replace('-', '_')])
 

Теперь pre будет либо префикс, либо пустой список, если нет тире. post всегда является полным суффиксом, с тире или без тире.

Ответ №2:

Вот решение с использованием регулярного выражения:

 >>> import re
>>> re.sub(r'(?<=-)(.*?)-', r'1_', 'abc-def-ghi-jkl')
'abc-def_ghi_jkl'
 

Он использует положительный внешний вид, чтобы соответствовать - символу, только если - перед ним в строке появляется другой символ. Это немного сложнее , чем самое простое решение split , но оно работает правильно, даже если входная строка не содержит никаких - символов.

Комментарии:

1. 1 означает всех персонажей, соответствующих (.*?) группе. Поскольку положительный поиск может быть только для строки фиксированной длины, регулярное выражение должно захватывать все символы между двумя - символами, поэтому эффективно в строке abc-def-ghi , которой оно соответствует def- , и заменяет ее def_ .