How can I extract tuples from a string?

Viewed 470

I have the following string:

r"(A1,B1,C1,D1),(A2,B2,C2,D2),..."

and I want to extract a list of tuples

[(A1,B1,C1,D1),(A2,B2,C2,D2),...]

A, B and D are integers, while C is a string enclosed in single quotes. The hard part is given by the fact that C might contain any character, included escaped single quotes (\'), commas (,), escaped backslashes (\\) and integers. I am trying to solve this problem using regexes, but I can't figure out how to do it.

So far, I've tried to match the end of the string by looking at the first single quote which is preceded by an even number of backslashes (0, 2, 4, ...), but I can't make it working. Any idea?

Expected results:

  • r"(21,3,'abc\',57',1993)" --> (21,3,'abc\',57',1993)
  • r"(21,3,'abc\\',1993)" --> (21,3,'abc\\',1993)
  • r"(21,3,'abc\\\\\',57\\\\',1993)" --> (21,3,'abc\\\\\',57\\\\',1993)
2 Answers

You can use ast.literal_eval to evaluate string containing python literals,

import ast
ip = r"(21,3,'abc\',57',1993)"
op = ast.literal_eval(ip)

print(op)
# output,
# (21, 3, "abc',57", 1993)


# verify that they are correct types,
for i in op:
    print("{} is {}".format(i, type(i)))

# output,
# 21 is <class 'int'>
# 3 is <class 'int'>
# abc',57 is <class 'str'>
# 1993 is <class 'int'>

You can use the pattern

(?<=')(?:\\\\|\\'|[^'])+(?=',)|\d+

For the string content (looks ahead and behind for 's), it'll repeat a group composed of either:

  • \\\\ - two backslashes (that is, represents a single literal backslash)
  • \\' - an escaped ' (that is, represents a single literal ')
  • [^'] - Anything but a quote character

Or, it'll match \d+, the integers.

https://regex101.com/r/5beqXJ/1

Related