2013-09-13 5 views
1

Так что я честно просто тупик, цель состоит в том, чтобы разделить на обертку, но не на ту же оболочку, если она находится в чем-то, что завернуто.regex split на рисунках обертывания

принять следующую строку:

s = 'something{now I am wrapped {I should not cause splitting} I am still wrapped}something else' 

результирующий список должен быть ['something','{','now I am wrapped {I should not cause splitting} I am still wrapped','}','something else']

Самое простое, что я попытался было findall, чтобы увидеть, как это может работать, но так как регулярное выражение не имеет памяти, он Безразлично 'Рассмотрите обертывание и, таким образом, он заканчивается, как только он найдет другую конечную скобку. Вот что случилось:

>>> s = 'something{now I am wrapped {I should not cause splitting} I am still wrapped}something else' 
>>> re.findall(r'{.*?}',s) 
['{now I am wrapped {I should not cause splitting}'] 

какие-либо идеи о том, как я мог заставить его признать не признавать, если это часть внутренней обертки?

+1

регулярное выражение представляет собой простой конечный автомат без памяти, как таковые, он не обрабатывает гнездования маркеров хорошо ...вам нужно посмотреть на что-то вроде yacc/lexx (у python есть модуль 'ply') см. этот связанный вопрос http://stackoverflow.com/questions/5454322/python-how-to-match-nested-parentheses-with-regex –

+0

который предлагает либо загрузить парсер (который я не могу сделать, потому что это для модуля, и я не хочу этого требовать), либо итерации по каждому символу, что кажется ненужным для чего-то столь простого –

+0

произвольные глубины вложенности не простая задача .... нужен парсер с памятью (не регулярное выражение) –

ответ

0

На основе всех ответов , Я решил просто написать функцию, которая берет строку и обертки и выводит список, используя переборную итерацию:

def f(string,wrap1,wrap2): 
    wrapped = False 
    inner = 0 
    count = 0 
    holds = [''] 
    for i,c in enumerate(string): 
     if c == wrap1 and not wrapped: 
      count += 2 
      wrapped = True 
      holds.append(wrap1) 
      holds.append('') 
     elif c == wrap1 and wrapped: 
      inner += 1 
      holds[count] += c 
     elif c == wrap2 and wrapped and inner > 0: 
      inner -= 1 
      holds[count] += c 
     elif c == wrap2 and wrapped and inner == 0: 
      wrapped = False 
      count += 2 
      holds.append(wrap2) 
      holds.append('') 
     else: 
      holds[count] += c 
    return holds 

и теперь это показывает, что он работает:

>>> s = 'something{now I am wrapped {I should not cause splitting} I am still wrapped}something else' 
>>> f(s,'{','}') 
['something', '{', 'now I am wrapped {I should not cause splitting} I am still wrapped', '}', 'something else'] 
+0

Вы должны пойти дальше и принять этот ответ. –

+0

Я не могу за 2 дня, если это мой собственный –

0

не уверен, что это всегда будет делать то, что вы хотите, но вы можете использовать partition и rpartition, как:

In [26]: s_1 = s.partition('{') 
In [27]: s_1 
Out[27]: 
('something', 
'{', 
'now I am wrapped {I should not cause splitting} I am still wrapped}something else') 
In [30]: s_2 = s_1[-1].rpartition('}') 
In [31]: s_2 
Out[31]: 
('now I am wrapped {I should not cause splitting} I am still wrapped', 
'}', 
'something else') 
In [34]: s_out = s_1[0:-1] + s_2 
In [35]: s_out 
Out[35]: 
('something', 
'{', 
'now I am wrapped {I should not cause splitting} I am still wrapped', 
'}', 
'something else') 
+0

нет, потому что я буду использовать это, чтобы организовать файл, который имеет много строк, подобных этому. фактическое «что-то» может содержать завернутые строки, которые также должны быть разделены. Имеет ли это смысл? –

1
s = 'something{now I am wrapped {I should not cause splitting} I am still wrapped}something else' 
m = re.search(r'(.*)({)(.*?{.*?}.*?)(})(.*)', s) 
print m.groups() 

новый ответ:

s = 'something{now I am wrapped {I should {not cause} splitting} I am still wrapped}something else' 
m = re.search(r'([^{]*)({)(.*)(})([^}]*)', s) 
print m.groups() 
+0

, который работает только для моего точного примера, а не для какого-то файла, где я не знаю, где находятся скобки и как он упорядочен. –

+0

действительно работает для всех тестовых случаев. Я просто запустил его ... но я сомневаюсь, что он будет работа с более чем двумя уровнями вложенности –

+0

не работает на 's = 'что-то {теперь я завернутый {я должен {вызывать} вызывать расщепление} Я все еще завернутый} что-то', но он должен работать только для одного уровня вложенности –

0

Вы можете решить эту проблему с помощью 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'] 
+0

, это менее исчерпывающий, чем тот ответ, который я использовал? –

+0

@ RyanSaxe: Не знаю. Кажется, он работает со всеми примерами, которые я видел в вопросе и некоторыми ответами. – Birei