Мой подход состоит в том, чтобы заменить все не заключенные в кавычки вхождения точки с запятой другим символом, который никогда не появится в тексте, а затем разделить на этот символ.В следующем коде используется функция re.sub с аргументом функции для поиска и замены всех вхождений строки srch
, не заключенных в одинарные или двойные кавычки или скобки, скобки или фигурные скобки, на строку repl
:
def srchrepl(srch, repl, string):
"""
Replace non-bracketed/quoted occurrences of srch with repl in string.
"""
resrchrepl = re.compile(r"""(?P<lbrkt>[([{])|(?P<quote>['"])|(?P<sep>["""
+ srch + """])|(?P<rbrkt>[)\]}])""")
return resrchrepl.sub(_subfact(repl), string)
def _subfact(repl):
"""
Replacement function factory for regex sub method in srchrepl.
"""
level = 0
qtflags = 0
def subf(mo):
nonlocal level, qtflags
sepfound = mo.group('sep')
if sepfound:
if level == 0 and qtflags == 0:
return repl
else:
return mo.group(0)
elif mo.group('lbrkt'):
if qtflags == 0:
level += 1
return mo.group(0)
elif mo.group('quote') == "'":
qtflags ^= 1 # toggle bit 1
return "'"
elif mo.group('quote') == '"':
qtflags ^= 2 # toggle bit 2
return '"'
elif mo.group('rbrkt'):
if qtflags == 0:
level -= 1
return mo.group(0)
return subf
Если вас не волнуют символы в скобках, вы можете значительно упростить этот код.
Скажем, вы хотите использовать в качестве замещающего символа трубу или вертикальную черту:
mylist = srchrepl(';', '|', mytext).split('|')
Кстати, здесь используется nonlocal
из Python 3.1, измените его на глобальный, если вам нужно.