Разделить строку на основе количества запятых

#python #regex

#python #регулярное выражение

Вопрос:

У меня есть текст, который разделен запятыми.

например:

 FOO( something, BOO(tmp, temp), something else)
  

Может быть, что-то еще содержит строку с запятыми…

Я хотел бы разделить текст внутри скобок FOO на его элементы, а затем передать элементы.

Что я знаю, так это то, что в FOO должно быть две запятые.

Как я мог бы разделить содержимое FOO на три его элемента?

что-то еще замечание: может быть BOO (ddd, ddd) или просто ddd. Я не могу предположить простое регулярное выражение ‘FOO ( w , BOO ( w , w ), w )’

Комментарии:

1. Итак, для приведенного выше примера вам нужен результат в виде: [ something , BOO(tmp, temp) , something else ]

Ответ №1:

Предполагая, что строка представляет собой код Python, вы можете использовать для этого синтаксический анализатор. Если вы внимательно посмотрите на результат, вы можете согласиться, что это не так плохо, как кажется на первый взгляд.

 >>> from parser import *
>>> source="FOO( something, BOO(tmp, temp), something)"
>>> st=suite(source)
>>> st2tuple(st)
(257, (268, (269, (270, (271, (272, (302, (306, (307, (308, (309, (312, (313, (314, (315, (316, (317, (318, (319, (320, (1, 'FOO')), (322, (7, '('), (330, (331, (302, (306, (307, (308, (309, (312, (313, (314, (315, (316, (317, (318, (319, (320, (1, 'something')))))))))))))))), (12, ','), (331, (302, (306, (307, (308, (309, (312, (313, (314, (315, (316, (317, (318, (319, (320, (1, 'BOO')), (322, (7, '('), (330, (331, (302, (306, (307, (308, (309, (312, (313, (314, (315, (316, (317, (318, (319, (320, (1, 'tmp')))))))))))))))), (12, ','), (331, (302, (306, (307, (308, (309, (312, (313, (314, (315, (316, (317, (318, (319, (320, (1, 'temp'))))))))))))))))), (8, ')')))))))))))))))), (12, ','), (331, (302, (306, (307, (308, (309, (312, (313, (314, (315, (316, (317, (318, (319, (320, (1, 'something'))))))))))))))))), (8, ')')))))))))))))))))), (4, ''))), (4, ''), (0, ''))
  

Комментарии:

1. я действительно не понимаю, что я должен видеть. Что означают числа (257, 268, …)?

2. Эти конкретные числа являются элементами в symbol.sym_name . 320 указывает, что что-то является «атомом». Анализатор также определил для вас круглые скобки и запятые. Я думаю, вы можете использовать регулярное выражение для просмотра строки в поисках либо знаков препинания, либо (320, (1, ‘whatever’ … , и чтобы регулярное выражение извлекало нужные вам биты. И я должен был упомянуть раздел 32.4 в руководстве по Python.

Ответ №2:

Вы можете использовать это регулярное выражение

 ,(?=(?:(?:([^)]*))?[^)]*) )$)
  

чтобы разделить вашу строку в запятых, бот не находится внутри BOO (…)

пример

Ответ №3:

Вы можете сделать это с помощью модуля регулярных выражений, который поддерживает рекурсию (полезно для работы с вложенными структурами):

 import regex

s = 'FOO( something, BOO(tmp, temp), something else)'

pat = regex.compile(r'''(?(DEFINE) # inside a definition group
    # you can define subpatterns to use later
    (?P<elt>     # define the subpattern "elt"
        [^,()]* 
        (?:
            ( (?amp;elt) (?: , (?amp;elt) )* )
            [^,()]*
        )* 
    )
)
# start of the main pattern
FOO( s*
    (?P<elt1> (?amp;elt) )  # capture group "elt1" contains the subpattern "elt"
    , s*
    (?P<elt2> (?amp;elt) )  # same here
    , s*
    (?P<elt3> (?amp;elt) )  # etc.
)''', regex.VERSION1 | regex.VERBOSE )

m = pat.search(s)

print(m.group('elt1'))
print(m.group('elt2'))
print(m.group('elt3'))
  

ДЕМОНСТРАЦИЯ

Ответ №4:

Предполагая, что вам нужен список элементов внутри FOO , поэтому сначала выполните его предварительную обработку

 >>> s = 'FOO( something, BOO(tmp, temp), something else)'
>>> s
'FOO( something, BOO(tmp, temp), something else)'
>>> s = re.sub(r'^[^(] (|)s*$','',s)
>>> s
' something, BOO(tmp, temp), something else'
  

Использование модуля регулярных выражений:

 >>> regex.split(r'[^,(] ([^)] )(*SKIP)(?!)|,', s)
[' something', ' BOO(tmp, temp)', ' something else']
  
  • [^,(] ([^)] )(*SKIP)(?!) чтобы пропустить шаблон [^,(] ([^)] )
  • |, альтернативный шаблон для фактического разделения входной строки, в данном случае это ,

другой пример:

 >>> t = 'd(s,sad,e),g(3,2),c(d)'
>>> regex.split(r'[^,(] ([^)] )(*SKIP)(?!)|,', t)
['d(s,sad,e)', 'g(3,2)', 'c(d)']