Аналогично ответу от AKX, но я уже был готов, когда увидел его. Кроме того, подход немного отличается (его легче адаптировать к другому формату), и результат может быть немного чище.
def parse(line):
parts = [""]
delims = ": ; !"
escape = False
for c in line:
if escape:
parts[-1] += c
escape = False
elif c == "%":
escape = True
elif c == delims[:1]:
parts += [""]
delims = delims[1:]
else:
parts[-1] += c
return [p for p in parts if p] if ";" not in delims else None
lines = ["a:b c ;","a%::b c ;","a%%:b c ; ! x","a%!:b c ; ! x","a%%%::b c ;","a:b incomplete"]
for line in lines:
print(line, "\t", parse(line))
По сути, это выполняет итерацию строки за символом, отслеживая «escape» mode "и проверяет текущий символ с помощью следующего ожидаемого разделителя.
Вывод:
a:b c ; ['a', 'b', 'c']
a%::b c ; ['a:', 'b', 'c']
a%%:b c ; ! x ['a%', 'b', 'c', ' x']
a%!:b c ; ! x ['a!', 'b', 'c', ' x']
a%%%::b c ; ['a%:', 'b', 'c']
a:b incomplete None