Разбор существующего файла конфигурации - PullRequest
4 голосов
/ 15 июня 2009

У меня есть файл конфигурации в следующем виде:

protocol sample_thread {
    { AUTOSTART 0 }
    { BITMAP thread.gif }
    { COORDS {0 0} }
    { DATAFORMAT {
        { TYPE hl7 }
        { PREPROCS {
            { ARGS {{}} }
            { PROCS sample_proc }
        } }
    } } 
}

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

Я искал другие анализаторы конфигурационных файлов, но ни один из обнаруженных мной файлов не может принять файл с таким синтаксисом.

Я ищу модуль, который может разобрать файл, как это, какие-либо предложения?

Если кому-то интересно, данный файл был сгенерирован Quovadx Cloverleaf.

Ответы [ 8 ]

11 голосов
/ 15 июня 2009

pyparsing очень удобен для быстрого и простого анализа, подобного этому. Чистый минимум будет что-то вроде:

import pyparsing
string = pyparsing.CharsNotIn("{} \t\r\n")
group = pyparsing.Forward()
group << pyparsing.Group(pyparsing.Literal("{").suppress() + 
                         pyparsing.ZeroOrMore(group) + 
                         pyparsing.Literal("}").suppress()) 
        | string

toplevel = pyparsing.OneOrMore(group)

Используйте его как:

>>> toplevel.parseString(text)
['protocol', 'sample_thread', [['AUTOSTART', '0'], ['BITMAP', 'thread.gif'], 
['COORDS', ['0', '0']], ['DATAFORMAT', [['TYPE', 'hl7'], ['PREPROCS', 
[['ARGS', [[]]], ['PROCS', 'sample_proc']]]]]]]

Оттуда вы можете получить все более изощренным, как вы хотите (анализировать номера отдельно от строк, искать конкретные имена полей и т. Д.). Вышеприведенное является довольно общим, просто ищет строки (определенные как любые непробельные символы, кроме "{" и "}") и {} разделенные списки строк.

2 голосов
/ 29 августа 2009

Используя еще один шаг решения Брайана для пирупинга, вы можете создать квазидериализатор для этого формата с помощью класса Dict:

import pyparsing

string = pyparsing.CharsNotIn("{} \t\r\n")
# use Word instead of CharsNotIn, to do whitespace skipping
stringchars = pyparsing.printables.replace("{","").replace("}","")
string = pyparsing.Word( stringchars )
# define a simple integer, plus auto-converting parse action
integer = pyparsing.Word("0123456789").setParseAction(lambda t : int(t[0]))
group = pyparsing.Forward()
group << ( pyparsing.Group(pyparsing.Literal("{").suppress() +
    pyparsing.ZeroOrMore(group) +
    pyparsing.Literal("}").suppress())
    | integer | string )

toplevel = pyparsing.OneOrMore(group)

sample = """
protocol sample_thread {
    { AUTOSTART 0 }
    { BITMAP thread.gif }
    { COORDS {0 0} }
    { DATAFORMAT {
        { TYPE hl7 }
        { PREPROCS {
            { ARGS {{}} }
            { PROCS sample_proc }
        } }
    } } 
    }
"""

print toplevel.parseString(sample).asList()

# Now define something a little more meaningful for a protocol structure, 
# and use Dict to auto-assign results names
LBRACE,RBRACE = map(pyparsing.Suppress,"{}")
protocol = ( pyparsing.Keyword("protocol") + 
             string("name") + 
             LBRACE + 
             pyparsing.Dict(pyparsing.OneOrMore(
                pyparsing.Group(LBRACE + string + group + RBRACE)
                ) )("parameters") + 
             RBRACE )

results = protocol.parseString(sample)
print results.name
print results.parameters.BITMAP
print results.parameters.keys()
print results.dump()

Печать

['protocol', 'sample_thread', [['AUTOSTART', 0], ['BITMAP', 'thread.gif'], ['COORDS', 

[0, 0]], ['DATAFORMAT', [['TYPE', 'hl7'], ['PREPROCS', [['ARGS', [[]]], ['PROCS', 'sample_proc']]]]]]]
sample_thread
thread.gif
['DATAFORMAT', 'COORDS', 'AUTOSTART', 'BITMAP']
['protocol', 'sample_thread', [['AUTOSTART', 0], ['BITMAP', 'thread.gif'], ['COORDS', [0, 0]], ['DATAFORMAT', [['TYPE', 'hl7'], ['PREPROCS', [['ARGS', [[]]], ['PROCS', 'sample_proc']]]]]]]
- name: sample_thread
- parameters: [['AUTOSTART', 0], ['BITMAP', 'thread.gif'], ['COORDS', [0, 0]], ['DATAFORMAT', [['TYPE', 'hl7'], ['PREPROCS', [['ARGS', [[]]], ['PROCS', 'sample_proc']]]]]]
  - AUTOSTART: 0
  - BITMAP: thread.gif
  - COORDS: [0, 0]
  - DATAFORMAT: [['TYPE', 'hl7'], ['PREPROCS', [['ARGS', [[]]], ['PROCS', 'sample_proc']]]]

Я думаю, что вы будете быстрее работать с pyparsing.

- Пол

1 голос
/ 15 июня 2009

Ваш конфигурационный файл очень похож на JSON (в значительной степени замените все ваши "{" и "}" на "[" и "]"). Большинство языков имеют встроенный анализатор JSON (PHP, Ruby, Python и т. Д.), И если нет, то есть библиотеки, которые могут его обработать.

Если вы не можете изменить формат файла конфигурации, вы можете прочитать все содержимое файла в виде строки и заменить все символы "{" и "}" любым удобным для вас способом. Затем вы можете проанализировать строку как JSON, и все готово.

1 голос
/ 15 июня 2009

Вы можете легко написать скрипт на python, который преобразует его в python dict, формат выглядит почти как иерархические пары «имя-значение», кажется, только проблема Coards {0 0}, где {0 0} не пара имя-значение, а список так кто знает какие еще такие случаи в формате Я думаю, что вам лучше всего иметь спецификацию для этого формата и написать простой скрипт на python для его прочтения.

1 голос
/ 15 июня 2009

Я постараюсь ответить на то, что я считаю недостающими вопросами ...

Файлы конфигурации доступны во многих форматах. Существуют хорошо известные форматы, такие как * .ini или apache config - в них, как правило, доступно много анализаторов.

Тогда есть пользовательские форматы. Это то, что кажется вам (это может быть какой-то четко определенный формат, который вы и я никогда раньше не видели - но пока вы не узнаете, что это такое, на самом деле это не имеет значения).

Я бы начал с программного обеспечения, из которого оно получено, и посмотрел, есть ли у них программный API, который может загружать / производить эти файлы. Если ничего не очевидно, позвоните в Quovadx. Скорее всего, кто-то уже решил эту проблему.

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

Написание синтаксического анализатора для этого формата не составит большого труда, если предположить, что ваш образец является представителем полного примера. Это иерархия значений, где каждый узел может содержать значение или дочернюю иерархию значений. После того, как вы определили основные типы, которые могут содержать значения, синтаксический анализатор становится очень простой структурой.

Вы можете написать это достаточно быстро, используя что-то вроде Lex / Flex или просто прямой синтаксический анализатор на выбранном вами языке.

0 голосов
/ 15 июня 2009

Посмотрите на LEX и YACC . Немного кривой обучения, но они могут генерировать парсеры для любого языка.

0 голосов
/ 15 июня 2009

Я немного искал в Cheese Shop , но не нашел ничего полезного для вашего примера. Проверьте страницу examples и этот специфический парсер (его синтаксис немного похож на ваш) Я думаю, что это должно помочь вам написать свой собственный.

0 голосов
/ 15 июня 2009

Может быть, вы могли бы написать простой скрипт, который преобразует ваш конфиг в файл xml и затем читает его, используя lxml, Beatuful Soup или что-то еще? И ваш конвертер может использовать PyParsing или регулярные выражения, например.

...