Вы можете решить эту проблему с помощью Scanner
из re
модуля:
Используя следующий список строк в качестве тест:
l = ['something{now I am wrapped {I should not cause splitting} I am still wrapped}everything else',
'something{now I am wrapped} here {and there} listen',
'something{now I am wrapped {I should {not} cause splitting} I am still wrapped}everything',
'something{now {I {am}} wrapped {I should {{{not}}} cause splitting} I am still wrapped}everything']
Создайте класс, в котором я буду сохранять состояние числа открытых и закрытых фигурных скобок, кроме текста между обоими ed из них. Он имеет три метода: один, когда совпадает с открытыми фигурными фигурными скобками, другой для закрывающего и последний для текста между ними. Зависит от того, если стек (opened_cb
переменная) пусто, я делать разные действия:
class Cb():
def __init__(self, results=None):
self.results = []
self.opened_cb = 0
def s_text_until_cb(self, scanner, token):
if self.opened_cb == 0:
return token
else:
self.results.append(token)
return None
def s_opening_cb(self, scanner, token):
self.opened_cb += 1
if self.opened_cb == 1:
return token
self.results.append(token)
return None
def s_closing_cb(self, scanner, token):
self.opened_cb -= 1
if self.opened_cb == 0:
t = [''.join(self.results), token]
self.results.clear()
return t
else:
self.results.append(token)
return None
И наконец, я создаю Scanner
и присоединиться результаты в простом списке:
for s in l:
results = []
cb = Cb()
scanner = re.Scanner([
(r'[^{}]+', cb.s_text_until_cb),
(r'[{]', cb.s_opening_cb),
(r'[}]', cb.s_closing_cb),
])
r = scanner.scan(s)[0]
for elem in r:
if isinstance(elem, list):
results.extend(elem)
else:
results.append(elem)
print('Original string --> {0}\nResult --> {1}\n\n'.format(s, results))
Здесь Полная программа и выполнение, чтобы увидеть результаты:
import re
l = ['something{now I am wrapped {I should not cause splitting} I am still wrapped}everything else',
'something{now I am wrapped} here {and there} listen',
'something{now I am wrapped {I should {not} cause splitting} I am still wrapped}everything',
'something{now {I {am}} wrapped {I should {{{not}}} cause splitting} I am still wrapped}everything']
class Cb():
def __init__(self, results=None):
self.results = []
self.opened_cb = 0
def s_text_until_cb(self, scanner, token):
if self.opened_cb == 0:
return token
else:
self.results.append(token)
return None
def s_opening_cb(self, scanner, token):
self.opened_cb += 1
if self.opened_cb == 1:
return token
return None
def s_closing_cb(self, scanner, token):
self.opened_cb -= 1
if self.opened_cb == 0:
t = [''.join(self.results), token]
self.results.clear()
return t
else:
self.results.append(token)
return None
for s in l:
results = []
cb = Cb()
scanner = re.Scanner([
(r'[^{}]+', cb.s_text_until_cb),
(r'[{]', cb.s_opening_cb),
(r'[}]', cb.s_closing_cb),
])
r = scanner.scan(s)[0]
for elem in r:
if isinstance(elem, list):
results.extend(elem)
else:
results.append(elem)
print('Original string --> {0}\nResult --> {1}\n\n'.format(s, results))
Запустить его как:
python3 script.py
Это дает:
Original string --> something{now I am wrapped {I should not cause splitting} I am still wrapped}everything else
Result --> ['something', '{', 'now I am wrapped {I should not cause splitting} I am still wrapped', '}', 'everything else']
Original string --> something{now I am wrapped} here {and there} listen
Result --> ['something', '{', 'now I am wrapped', '}', ' here ', '{', 'and there', '}', ' listen']
Original string --> something{now I am wrapped {I should {not} cause splitting} I am still wrapped}everything
Result --> ['something', '{', 'now I am wrapped {I should {not} cause splitting} I am still wrapped', '}', 'everything']
Original string --> something{now {I {am}} wrapped {I should {{{not}}} cause splitting} I am still wrapped}everything
Result --> ['something', '{', 'now {I {am}} wrapped {I should {{{not}}} cause splitting} I am still wrapped', '}', 'everything']
регулярное выражение представляет собой простой конечный автомат без памяти, как таковые, он не обрабатывает гнездования маркеров хорошо ...вам нужно посмотреть на что-то вроде yacc/lexx (у python есть модуль 'ply') см. этот связанный вопрос http://stackoverflow.com/questions/5454322/python-how-to-match-nested-parentheses-with-regex –
который предлагает либо загрузить парсер (который я не могу сделать, потому что это для модуля, и я не хочу этого требовать), либо итерации по каждому символу, что кажется ненужным для чего-то столь простого –
произвольные глубины вложенности не простая задача .... нужен парсер с памятью (не регулярное выражение) –