Найти - Пользователи
Полная версия: Регулярные выражения вложенные структуры
Начало » Python для новичков » Регулярные выражения вложенные структуры
1
romensd
нужна регулярка которая умеет извлекать текст из скобок по уровню
для этого я буду использовать рекурсию

исходная строка
level_1<level_2<level_3,level_3<level_4,level_4>>,level_2<level_3,level_3>>

на 1 этапе получить строку в скобках level_1
level_2<level_3,level_3<level_4,level_4>>,level_2<level_3,level_3>
на 2 этапе получить строку в скобках level_2
level_3,level_3<level_4,level_4>
level_3,level_3 - конец рекурсии

на 3 этапе получить строку в скобках level_3
level_4,level_4 - конец рекурсии

в скобках <> может быть:
1. строка level_n
2. level_1< level_2>
3. level_1< level_2,level_2>
4. level_1< level_2<level_n,…>,level_2>


вопрос в том как корректно извлекать сроки относительно уровня вложенности
Shaman
Почему нужна именно регулярка, а не что-нибудь другое?
doza_and
Регулярные выражения для этого плохо подходят. Посмотрите pyparsing
romensd
Пример кода можно на pyparsing ?
sander
romensd
сотни их
romensd
как распарсить строку
level_1<level_2_1<level_3,level_3_1<level_4,level_4_1>>,level_2_2<level_3,level_3_1_1>>
так, чтобы образовался вложений словарь
{“level_1” : {“level_2_1” : {“level_3”:{},“level_3_1”:{“level_4”:{},“level_4”:{}}} , “level_2_2”:{“level_3”:{},“level_3_1”:{}}}}
py.user.next
#!/usr/bin/env python3
 
"""
Convert:
 
level_1<level_2_1<level_3,level_3_1<level_4,level_4_1>>,level_2_2<level_3,level_3_1_1>>
 
To:
 
{'level_1':
    {'level_2_1':
        {'level_3': {},
         'level_3_1':
            {'level_4': {},
             'level_4': {}}},
     'level_2_2':
         {'level_3': {},
          'level_3_1': {}}}}
 
"""
 
import re
 
def make_tokens(s):
    pat = r'level[_\d]+|<|,|>'
    out = []
    for i in re.findall(pat, s):
        if i.startswith('level'):
            out.append(('name', i))
        elif i == '<':
            out.append(('open', i))
        elif i == ',':
            out.append(('sep', i))
        elif i == '>':
            out.append(('close', i))
    return out
 
def make_tree(tokens):
    out = []
    stack = []
    cur = out
    for t, v in tokens:
        if t == 'name':
            cur.extend([v, []])
        elif t == 'open':
            stack.append(cur)
            cur = cur[-1]
        elif t == 'close':
            cur = stack.pop()
        elif t == 'sep':
            pass
    return out
 
 
s = 'level_1<level_2_1<level_3,level_3_1<level_4,level_4_1>>,level_2_2<level_3,level_3_1_1>>'
 
out = make_tree(make_tokens(s))
 
import pprint
pprint.pprint(out)

[guest@localhost py]$ ./synt.py 
['level_1',
['level_2_1',
['level_3', [], 'level_3_1', ['level_4', [], 'level_4_1', []]],
'level_2_2',
['level_3', [], 'level_3_1_1', []]]]
[guest@localhost py]$


Словари не являются упорядоченными, поэтому последовательность элементов может меняться произвольно, и не может быть одинаковых ключей .
>>> {'level_1':
...     {'level_2_1':
...         {'level_3': {},
...          'level_3_1':
...             {'level_4': {},
...              'level_4': {}}},
...      'level_2_2':
...          {'level_3': {},
...           'level_3_1': {}}}}
{'level_1': {'level_2_2': {'level_3': {}, 'level_3_1': {}}, 'level_2_1': {'level_3': {}, 'level_3_1': {'level_4': {}}}}}
>>>
romensd
как возможно написать парсер который возвращает количество чилдренов

level_1<
      level_2_1<
		  level_3,
		  level_3_1<level_4,level_4_1>>,
      level_2_2<level_3,level_3_1_1>

В level_1 их два (level_2_1,level_2_2) и т.д.

кортеж ('уровень' , ‘количество чилдренов’)
повторение уровней не важны
[
  (level_1, 2)
  (level_2_1,2),
  (level_2_2,2),
  (level_3,0)
  (level_3_1,2)
  (level_4,0)
  (level_4_1,0)
  (level_3,0)
  (level_3_1,1)
]

В парсер желательно не привязываться к слову level.
Строку я написал для примера, могут быть другие слова.
Количество чилдренов может быть разная.
Пока большое спасибо, очень помогли.
py.user.next
#!/usr/bin/env python3
 
"""
Convert:
 
level_1<level_2_1<level_3,level_3_1<level_4,level_4_1>>,level_2_2<level_3,level_3_1_1>>
 
To:
 
{'level_1':
    {'level_2_1':
        {'level_3': {},
         'level_3_1':
            {'level_4': {},
             'level_4': {}}},
     'level_2_2':
         {'level_3': {},
          'level_3_1': {}}}}
 
"""
 
import re
 
def make_tokens(s):
    pat = r'level[_\d]+|<|,|>'
    out = []
    for i in re.findall(pat, s):
        if i.startswith('level'):
            out.append(('name', i))
        elif i == '<':
            out.append(('open', i))
        elif i == ',':
            out.append(('sep', i))
        elif i == '>':
            out.append(('close', i))
    return out
 
def make_tree(tokens):
    out = []
    stack = []
    cur = out
    for t, v in tokens:
        if t == 'name':
            cur.extend([v, []])
        elif t == 'open':
            stack.append(cur)
            cur = cur[-1]
        elif t == 'close':
            cur = stack.pop()
        elif t == 'sep':
            pass
    return out
 
def make_children(tree):
    out = []
    name = ''
    for i in tree:
        if isinstance(i, str):
            name = i
        elif isinstance(i, list):
            out.append((name, len(i) // 2))
            out.extend(make_children(i))
    return out
 
 
s = 'level_1<level_2_1<level_3,level_3_1<level_4,level_4_1>>,level_2_2<level_3,level_3_1_1>>'
 
tree = make_tree(make_tokens(s))
out = make_children(tree)
 
import pprint
pprint.pprint(out)

[guest@localhost py]$ ./synt.py 
[('level_1', 2),
('level_2_1', 2),
('level_3', 0),
('level_3_1', 2),
('level_4', 0),
('level_4_1', 0),
('level_2_2', 2),
('level_3', 0),
('level_3_1_1', 0)]
[guest@localhost py]$

Обход другой немного. Так хоть понятно, что в чём находится.
romensd
Очень круто . Большое спасибо
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB