Получить пары ключ=значение из строки с помощью регулярного выражения

У меня есть строка, которая выглядит примерно так:

x = """\
names=['m','c'],  \
nmodes=2,  \
mus=[[-5.0,  -5.0],  \
[5.0,  5.0]],  \
sigmas=[[1.5,  1.5],  [2.1,  2.1]],  \
corrcoefs=[[[1.0,  -0.7],  [-0.7,  1.0]],  [[1.0,  0.7],  [0.7,  1.0]]],  \
covs=[[[2.25,  -1.5749999999999997],  [-1.5749999999999997,  2.25]],  [[4.41,  3.087],  [3.087,  4.41]]],  \
weights=[1.0,  3.0],  \
bounds = {'m': (-inf,  inf),  'c': (-inf,  inf)}\
"""

Я хочу разбить его на пары ключ-значение, используя «=» в качестве разделителя и где каждая пара разделена запятой ",".

Я пробовал следующее, используя re:

import re

re.findall("(\S+)=(\[.*\]$|{.*}$|\S+)", x)

который дает:

[('names', "['m','c'],"),
 ('nmodes', '2,'),
 ('mus', '[[-5.0,'),
 ('sigmas', '[[1.5,'),
 ('corrcoefs', '[[[1.0,'),
 ('covs', '[[[2.25,'),
 ('weights', '[1.0,'),
 ('bounds', "{'m': (-inf,  inf),  'c': (-inf,  inf)}")]

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

Какова логика матчей? Должны ли они быть сбалансированными кронштейнами?

The fourth bird 06.05.2022 21:01

В идеале часть «значение» может быть любой строкой до последней запятой перед следующим ключом. Поскольку у меня были значения, которые были списками или словарями, которые сами содержали запятые, моя логика заключалась в том, чтобы попытаться включить эти случаи.

Matt Pitkin 06.05.2022 21:08

Вы не должны использовать $, ваша строка не имеет разрывов строк.

Wiktor Stribiżew 06.05.2022 21:13
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
3
42
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ты можешь использовать

re.findall(r'(\w+)=(\[.*?]|{.*?}|\S+)(?=\s*,\s*\w+=|\Z)', text)

См. демонстрация регулярных выражений. Подробности:

  • (\w+) - Группа 1: один или несколько символов слова
  • = - = символ
  • (\[.*?]|{.*?}|\S+) - Группа 2: [, любой ноль или более символов, кроме символов разрыва строки, как можно меньше, ] или {, любой ноль или более символов, кроме символов разрыва строки, как можно меньше, }, или один или более символы без пробелов
  • (?=\s*,\s*\w+=|\Z) - положительный просмотр вперед, для которого требуется запятая, заключенная в ноль или более пробелов, один или несколько символов слова, = или конец строки.

Другие вопросы по теме