How can I find the keyword argument passed to a c-style
python string
Given:
bill eats apple
'%(name)s eats %(fruit)s'
Should get
{ 'name': 'bill', 'fruit' : 'apple'}
How can I find the keyword argument passed to a c-style
python string
Given:
bill eats apple
'%(name)s eats %(fruit)s'
Should get
{ 'name': 'bill', 'fruit' : 'apple'}
First, there is no function or package in Python that allow you to do that with old style (aka C style) string formatting. A good reference about reversing c-style string format.
The best you can have is a giant regex pattern and as you know it's really not a perfect solution.
That said,
As @smarx said in comments, you can use parse
which is well fitted for that, but, from the given doc's link:
parse() is the opposite of format()
That mean you needs to use format()
instead of %
, which is a good thing because %
is Python's string formatting old style where format()
is the new style and the best to use since Python3 (it's python 2.7 / 3 compliant, but not %
).
Here is an example with format()
:
print(parse.parse('{name} eats {fruit}', 'bill eats apple'))
<Result () {'fruit': 'apple', 'name': 'bill'}>
If you are not confortable with format()
I advise you to give a look at pyformat.org, a really good guide.
If you do not want to use parse
, you can convert your pattern string to a regular expression using named groups and then use re.match
and match.groupdict
to get the mapping.
>>> text = "bill eats apple"
>>> a = "%(name)s eats %(fruit)s"
>>> p = re.sub(r"%\((\w+)\)s", r"(?P<\1>\w+)", a)
>>> p
'(?P<name>\\w+) eats (?P<fruit>\\w+)'
>>> re.match(p, text).groupdict()
{'fruit': 'apple', 'name': 'bill'}
Note that \w+
will only match a single word. To allow for more complex names, you might instead use e.g. [^(]+
to match anything up to the closing )
>>> text = "billy bob bobbins eats a juicy apple"
>>> p = re.sub(r"%\((\w+)\)s", r"(?P<\1>[^)]+)", a)
>>> re.match(p, text).groupdict()
{'fruit': 'a juicy apple', 'name': 'billy bob bobbins'}