How to turn %s into {0}, {1} ... less clunky?

Using re.sub for dynamic replacing:

import re

text = "A %s B %s %s B %s"


def _fix_substitution_parms(raw_message):
    counter = 0
    def replace(_):
        nonlocal counter
        counter += 1
        return '{{{}}}'.format(counter - 1)
    return re.sub('%s', replace, raw_message)


print(_fix_substitution_parms(text))  # A {0} B {1} {2} B {3}

I would do what Reznik originally suggested and then call .format on that:

def _fix_substitution_parms(raw_message: str) -> str:
    num_to_replace = raw_message.count("%s")
    python_format_string_message = raw_message.replace("%s", "{{{}}}")
    final_message = python_format_string_message.format(*range(num_to_replace))
    return final_message

Use re.sub with a lambda function for reapplying the substitution once for each element, and itertools.count for getting numbers sequentially:

import itertools
import re

s = "A %s B %s"

counter = itertools.count()
result = re.sub('%s', lambda x: f'{{{next(counter)}}}', s)
print(result)  # 'A {0} B {1}'

Remember to wrap this in a function to perform this operation more than once, since you'll need to refresh itertools.count.


I think that shoudl work

rv.replace('%s','{{{}}}').format(*range(rv.count('%s')))