Assuming that you don't have anything in your string more nested than what is in your example, you could first use lookahead/lookbehind assertions to split the string into your key-value pairs, looking for the pattern } {
(the end of one pair of brackets and the beginning of another.)
>>> str = '{key1 value1} {key2 value2} {key3 {value with spaces}}'
>>> pairs = re.split('(?<=})\s*(?={)', str)
This says "Match on any \s*
(whitespace) that has a }
before it and a {
after it, but don't include those brackets in the match itself."
Then you have your key-value pairs:
>>> pairs
['{key1 value1}', '{key2 value2}', '{key3 {value with spaces}}']
which can be split on whitespace with the maxsplit
parameter set to 1, to make sure that it only splits on the first space. In this example I have also used string indexing (the [1:-1]
) to get rid of the curly braces that I know are at the beginning and end of each pair.
>>> simple = pairs[0]
>>> complex = pairs[2]
>>> simple
'{key1 value1}'
>>> complex
'{key3 {value with spaces}}'
>>> simple[1:-1]
'key1 value1'
>>> kv = re.split('\s+', simple[1:-1], maxsplit=1)
>>> kv
['key1', 'value1']
>>> kv3 = re.split('\s+', complex[1:-1], maxsplit=1)
>>> kv3
['key3', '{value with spaces}']
then just check whether the value is enclosed in curly braces, and remove them if you need to before putting them into your dictionary.
If it is guaranteed that the key/value pairs will always be separated by a single space character, then you could use plain old string split instead.
>>> kv3 = complex[1:-1].split(' ', maxsplit=1)
>>> kv3
['key3', '{value with spaces}']