Cпарсить C-подобный формат на python

Нужно сделать парсер вот такого формата, как это можно сделать? Заранее спасибо!

"Users"
{
    "STEAM_0:0:15256262"
    {
        "name"   "polly"
        "expires"   "0"
        "flags"   "0a0b0c0d0h0n0p0t0w0x1b1e1f1h1k1n0z"
    }
    "STEAM_0:1:24536789"
    {
        "name"   "test_user"
        "expires"   "0"
        "flags"   "0a0b0c0d0h0n0p0t0w0x1b1e1f1h1k1n0z"
    }

}

Нужно, чтобы на выходе парсер выдавал что-то типо:

[{"steam_id": "STEAM_0:0:15256262", "name": "polly", "expires": "0", "0a0b0c0d0h0n0p0t0w0x1b1e1f1h1k1n0z"},
 {"steam_id": "STEAM_0:1:24536789", "name": "test_user", "expires": "0", "0a0b0c0d0h0n0p0t0w0x1b1e1f1h1k1n0z"}]

Ответы (2 шт):

Автор решения: Just_a_programmer

Если первый блок это файл, информацию из которого ты хочешь спарсить, то открой файл и в строковую переменную запиши спарсенный текст. file = open('путь к файлу', 'r') txt = file.read() Дальше есть строковые методы, ищешь ключевые фразы, например:

"name"

и смотришь на слова после них.

→ Ссылка
Автор решения: gil9red

Накидал простенький парсер:

  • Перебираем построчно и считаем количество открывающих и закрывающих скобок
  • Заполняем данные в зависимости от текущего уровня вложенности
    • Для первого уровня, т.е. steam_id достаточно вернуть строку без первого и последнего символа
    • Для вытаскивания ключ-значений типа name используется регулярное выражение "(.+?)"\s+"(.+?)", которое означает поиск в строке пары кавычек с текстом внутри ("(.+?)"), разделенными пробелами (\s+)

Пример:

import re


text = """\
"Users"
{
    "STEAM_0:0:15256262"
    {
        "name"   "polly"
        "expires"   "0"
        "flags"   "0a0b0c0d0h0n0p0t0w0x1b1e1f1h1k1n0z"
    }
    "STEAM_0:1:24536789"
    {
        "name"   "test_user"
        "expires"   "0"
        "flags"   "0a0b0c0d0h0n0p0t0w0x1b1e1f1h1k1n0z"
    }
}
"""

items = []
current_level = 0

for line in text.splitlines():
    line = line.strip()
    if line == '{':
        current_level += 1
        continue
    elif line == '}':
        current_level -= 1
        continue

    if current_level == 1:
        steam_id = line[1:-1]
        items.append({'steam_id': steam_id})

    elif current_level == 2:
        m = re.search(r'"(.+?)"\s+"(.+?)"', line)
        key, value = m.group(1), m.group(2)
        items[-1][key] = value

print(items)

Результат:

[{'steam_id': 'STEAM_0:0:15256262', 'name': 'polly', 'expires': '0', 'flags': '0a0b0c0d0h0n0p0t0w0x1b1e1f1h1k1n0z'}, {'steam_id': 'STEAM_0:1:24536789', 'name': 'test_user', 'expires': '0', 'flags': '0a0b0c0d0h0n0p0t0w0x1b1e1f1h1k1n0z'}]

PS.

Если считывать из файла, то есть такие варианты:

  1. Считать в переменную:

    with open('путь до файла', encoding='utf-8') as f:
        text = f.read()
        ...
    
  2. Считывать из файла построчно:

    with open('путь до файла', encoding='utf-8') as f:
        items = []
        current_level = 0
    
        for line in f:
            ...
    
    

Второй вариант особенно подходит, когда файл не влезет в память

→ Ссылка