Получения текста в скобках учитывая возможные вложенные скобки
Мне нужно достать весь текст из скобки после определённого текста, например после текста example. Раньше я пытался делать с помощью re и паттерна r'example\(.*?\)'
, но при вложенной скобке он остановится на вложенной закрывающей скобке. Как лучше решить это?
Ответы (1 шт):
Это можно сделать простым поиском со стеком
def find_next_matching_parens(s: str, pos: int, immediate=False) -> tuple[int, int]:
"""
Находит следующую пару соответствующих круглых скобок в строке.
Args:
s (str): Входная строка, в которой производится поиск.
pos (int): Позиция в строке, с которой начинается поиск.
immediate (bool, optional): Если True, функция проверяет, что символ в позиции pos является открывающей скобкой.
Если это не так, возвращает (None, None). По умолчанию False.
Returns:
tuple[int, int]: Кортеж из двух элементов, где первый элемент - индекс открывающей скобки,
а второй элемент - индекс закрывающей скобки. Если соответствующая закрывающая скобка не найдена,
возвращает (start, None). Если открывающая скобка не найдена, возвращает (-1, None).
"""
if immediate and s[pos] != "(":
return None,None
stack = []
start = s.find("(", pos)
if start == -1:
return -1, None
for i in range(start, len(s)):
if s[i] == "(":
stack.append(i)
elif s[i] == ")":
start = stack.pop()
if len(stack) == 0:
return start, i
return start, None
def get_paren_text_after_name(s: str, name: str, immediate: bool = True) -> str:
"""
Возвращает текст в скобках, следующий за указанным именем в строке.
Аргументы:
s (str): Исходная строка для поиска.
name (str): Имя, после которого нужно найти текст в скобках.
immediate (bool): Если True, ищет ближайшие скобки сразу после имени.
Если False, ищет следующие скобки после имени. По умолчанию True.
Возвращает:
str: Текст в скобках, следующий за именем, или None, если имя не найдено
или скобки не найдены.
"""
pos = s.find(name)
if pos == -1:
print("Имя не найдено")
return None
pos += len(name)
start, end = find_next_matching_parens(s, pos, immediate=immediate)
if start is None or end is None:
print("Скобки не найдены")
return None
return s[start + 1:end]
Пример:
sample = "aaa(bbbb(cc1,cc2), dddd) + e"
print(find_next_matching_parens(sample, 1)) # Результат: (3,23)
print(find_next_matching_parens(sample, 14)) # Результат: (-1,None)
print(get_paren_text_after_name(sample, "bbbb")) # Результат: "cc1,cc2"
Функция find_next_matching_parens
ищет пару скобок, функция get_paren_text_after_name
ищет имя,затем за ним скобки, и извлекает текст между скобками. Это,понятное дело, пример. Вы можете доработать его, например, заменив поиск по имени на поиск по регулярному выражению. Или добавить пропуск пробелов между именем и скобкой. Вариантов много, подгоняйте под себя.