Search code examples
pythonstringf-string

Is there a simple way to extract variable values given a formatted f-string and the original template?


Assume we have an f-string-style template:

"{kid} ate {number} {fruit}"

and a formatted version of that:

"Jack ate 42 apples"

How could I, very generally, extract "Jack", "42", and "apples" from this string based on the fact that they match kid, number, and fruit respectively? Assume that the f-string could be anything and contain any number of simple string or integer variables (no formatting instructions), and that the string for extraction has already been generated from that f-string, and so matches it perfectly. This also means that I can't use regex rather than f-string-style formatting, unless there's a way to generate a regex based on the f-string.

I already have something that works for my case, but it's not general, and feels a little hacky to me. I feel like there must be something simpler that I just can't find the right words to google:

template = "{kid} ate {number} {fruit}"
example = "Jack ate 42 apples"
extracted = {"kid": "", "number": "", "fruit": ""}
for variable in extracted.keys():
    extracted[variable] = example
    for chunk in template.split(f"{{variable}}"):
        extracted[variable] = extracted[variable].replace(chunk, "")

If it's not possible to get both more simple and more general, then more simple with the same level of generality would be great too :)


Solution

  • You can do this with regex and match group like this:

    • To create a group with name: (?'name')
    • Match any characters unlimited times: .+
    import re
    
    pattern = r"(?P<name>.+) ate (?P<number>.+) (?P<fruit>.+)"
    
    text = "John ate 3 apples"
    match = re.match(pattern, text)
    
    if match:
        name = match.group('name')
        number = match.group('number')
        fruit = match.group('fruit')
        print(f"{name} ate {number} {fruit}")
    else:
        print("Pattern not found in the text.")
    
    

    I hope this is what you want