4

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)
3
  • 1
    The re.sub docs have an example of using a function for repl. Also be aware that {} have special meaning within regex and will need to be escaped if you want a literal match. Commented Apr 7, 2020 at 14:46
  • 1
    @0x5453 No, {{.*?}} is a valid pattern. No need to escape anything. It is not Android or C++ (MSVC). Commented Apr 7, 2020 at 14:46
  • You may consider ` re.sub(r'{{(\w+),(\w+)}}', lambda x: x.group(random.choice([1,2])), s)`, but it will support just two values. Do you want to produce a single result, or all possible permutations? Commented Apr 7, 2020 at 14:51

2 Answers 2

4

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)
Sign up to request clarification or add additional context in comments.

Comments

2

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

2 Comments

Thank you for your answer. I'd like the custom replacement function to work for any length of the list (here only 2 items), do you have any idea?
@Basj, Splitting is the option for any length list. But for small lengths, you can see using the approach in my answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.