Replace with a custom function with Python re

Viewed 784

For a string

s = '{{a,b}} and {{c,d}} and {{0,2}}'

I'd like to replace every {{...}} pattern by randomly one of the items in the list inside, i.e.:

"a and d and 2"  
"b and d and 0"  
"b and c and 0"
...

I remember that there's a way in module re to not simply replace like re.sub, but have a custom replacement function, but I can't find this anymore in the doc (maybe I'm searching with wrong keywords...)

This doesn't give any output:

import re

r = re.match('{{.*?}}', '{{a,b}} and {{c,d}} and {{0,2}}')
for m in r.groups():
    print(m)
2 Answers

You could use

import random, re

def replace(match):
    lst = match.group(1).split(",")
    return random.choice(lst)

s = '{{a,b}} and {{c,d}} and {{0,2}}'

s = re.sub(r"{{([^{}]+)}}", replace, s)
print(s)

Or - if you're into one-liners (not advisable though):

s = re.sub(
    r"{{([^{}]+)}}", 
    lambda x: random.choice(x.group(1).split(",")), 
    s)

You can avoid splitting using appropriate regex to fetch patterns:

import re, random

s = '{{a,b}} and {{c,d}} and {{0,2}}'
s = re.sub(r'{{(.*?),(.*?)}}', random.choice(['\\1', '\\2']), s)

# a and c and 0
Related