pythonuuidf-string

regex to match uuid4 not working with f-string


Working:

#!/usr/bin/python3

import re

path = "/a/b/c/e72cc82c-e83a-431c-9f63-c8d80eec9307"

if re.match(r"/a/b/c/[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}$", path):
    print("matched")
else:
    print("didn't match anything")

Failing:

#!/usr/bin/python3

import re

PATH_PREFIX = "/a/b/c"
path = "/a/b/c/e72cc82c-e83a-431c-9f63-c8d80eec9307"

if re.match(rf"{PATH_PREFIX}/[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}$", path):
    print("matched")
else:
    print("didn't match anything")

I used the f-string in python regex a few years ago, and it was working. Not sure why it is failing now.


Solution

  • you can print the pattern of your f-string regex.

    reg = re.compile(rf"{PATH_PREFIX}/[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}$")
    print(reg.pattern)
    

    and it shows:

    /a/b/c/[a-f0-9]8-[a-f0-9]4-4[a-f0-9]3-[89aAbB][a-f0-9]3-[a-f0-9]12$
    

    while the correct one should be:

    /a/b/c/[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}$
    

    so if you want to match the {} character themself in f-string, use {{}} instead.

    import re
    
    PATH_PREFIX = "/a/b/c"
    path = "/a/b/c/e72cc82c-e83a-431c-9f63-c8d80eec9307"
    
    wrong_reg = re.compile(rf"{PATH_PREFIX}/[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}$")
    print(wrong_reg.pattern)  # /a/b/c/[a-f0-9]8-[a-f0-9]4-4[a-f0-9]3-[89aAbB][a-f0-9]3-[a-f0-9]12$
    correct_reg = re.compile(rf"{PATH_PREFIX}/[a-f0-9]{{8}}-[a-f0-9]{{4}}-4[a-f0-9]{{3}}-[89aAbB][a-f0-9]{{3}}-[a-f0-9]{{12}}$")
    print(correct_reg.pattern)  # /a/b/c/[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}$
    if correct_reg.match(path):
        print("matched")
    else:
        print("didn't match anything")