Skip to content

Instantly share code, notes, and snippets.

@fitoprincipe
Last active February 18, 2022 12:39
Show Gist options
  • Save fitoprincipe/10f76e266ae9c52c26858d69fc84e4c0 to your computer and use it in GitHub Desktop.
Save fitoprincipe/10f76e266ae9c52c26858d69fc84e4c0 to your computer and use it in GitHub Desktop.
match format string
def match_format_string(format_str, s):
""" https://stackoverflow.com/questions/10663093/use-python-format-string-in-reverse-for-parsing
Match s against the given format string, return dict of matches.
We assume all of the arguments in format string are named keyword arguments (i.e. no {} or
{:0.2f}). We also assume that all chars are allowed in each keyword argument, so separators
need to be present which aren't present in the keyword arguments (i.e. '{one}{two}' won't work
reliably as a format string but '{one}-{two}' will if the hyphen isn't used in {one} or {two}).
We raise if the format string does not match s.
Example:
fs = '{test}-{flight}-{go}'
s = fs.format(test='first', flight='second', go='third')
match_format_string(fs, s) -> {'test': 'first', 'flight': 'second', 'go': 'third'}
"""
# First split on any keyword arguments, note that the names of keyword arguments will be in the
# 1st, 3rd, ... positions in this list
tokens = re.split(r'\{(.*?)\}', format_str)
keywords = tokens[1::2]
# Now replace keyword arguments with named groups matching them. We also escape between keyword
# arguments so we support meta-characters there. Re-join tokens to form our regexp pattern
tokens[1::2] = map(u'(?P<{}>.*)'.format, keywords)
tokens[0::2] = map(re.escape, tokens[0::2])
pattern = ''.join(tokens)
# Use our pattern to match the given string, raise if it doesn't match
matches = re.match(pattern, s)
if not matches:
raise Exception("Format string did not match")
# Return a dict with all of our keywords and their values
return {x: matches.group(x) for x in keywords}
@fitoprincipe
Copy link
Author

This is a very useful code that I find myself using in many project. So I share ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment