Pergunta

Eu tenho um arquivo de configuração que está na seguinte forma:

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

O arquivo real pode não ter esses campos exatos, e eu prefiro não precisar descrever a estrutura dos dados é para o analisador antes que ele analise.

Procurei outros analisadores de arquivos de configuração, mas nenhum que eu achei que parece ser capaz de aceitar um arquivo dessa sintaxe.

Estou procurando um módulo que possa analisar um arquivo como esse, alguma sugestão?

Se alguém estiver curioso, o arquivo em questão foi gerado pelo Quovadx Cloverleaf.

Foi útil?

Solução

Pyparsing é bastante útil para análise rápida e simples assim. Um mínimo nu seria algo como:

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)

O use como:

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

A partir daí, você pode ficar mais sofisticado como você deseja (números de análise separadamente de strings, procure nomes de campo específicos etc.). O exposto acima é bastante geral, apenas procurando strings (definido como qualquer caractere não-branco, exceto "{" e "}") e {} listas delimitadas de strings.

Outras dicas

Tomando outra etapa de Pyparsing de Brian, você pode criar um quase-desserializador para este formato usando a classe 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()

Impressões

['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']]]]

Eu acho que você ficará mais rápido com o Pyparsing.

-- Paulo

Vou tentar responder o que acho que são as perguntas que faltam ...

Os arquivos de configuração vêm em muitos formatos. Existem formatos bem conhecidos como *.ini ou Apache Config - estes tendem a ter muitos analisadores disponíveis.

Depois, existem formatos personalizados. É isso que parece ser o seu (pode ser um formato bem definido, você e eu nunca vimos antes - mas até que você saiba o que isso realmente não importa).

Eu começaria com o software que veio e veria se eles possuem uma API de programação que pode carregar/produzir esses arquivos. Se nada for óbvio, ligue para Quovadx. Provavelmente, alguém já resolveu esse problema.

Caso contrário, você provavelmente está por conta própria para criar seu próprio analisador.

Escrever um analisador para esse formato não seria muito difícil, assumindo que sua amostra é representativa de um exemplo completo. É uma hierarquia de valores em que cada nó pode conter um valor ou uma hierarquia infantil de valores. Depois de definir os tipos básicos que os valores podem conter o analisador é uma estrutura muito simples.

Você pode escrever isso razoavelmente rapidamente usando algo como Lex/Flex ou apenas um analisador direto no idioma da sua escolha.

Você pode escrever facilmente um script no Python que o converterá em ditado de python, o formato parece quase pares de valor de nome hierárquico, apenas o problema parece ser colapso {0 0}, onde {0 0} não é um par de valor de nome, mas Uma lista para quem sabe o que outros casos estão no formato, acho que sua melhor aposta é ter especificações para esse formato e escrever um script python simples para lê -lo.

Seu arquivo de configuração é muito semelhante a JSON (praticamente, substitua todos os seus "{" e "}" com [" e "]). A maioria dos idiomas possui um analisador JSON embutido (PHP, Ruby, Python, etc.) e, se não, existem bibliotecas disponíveis para lidar com isso para você.

Se você não puder alterar o formato do arquivo de configuração, poderá ler todo o conteúdo do arquivo como uma string e substituir todos os caracteres "{" e "}" por qualquer meio que você preferir. Então você pode analisar a string como JSON e está definido.

Eu procurei um pouco no Queijaria, mas não encontrei nada útil para o seu exemplo. Verifica a Exemplos página e isto O analisador específico (é a sintaxe se assemelha um pouco ao seu). Eu acho que isso deve ajudá -lo a escrever o seu.

Investigar Lex e Yacc. Um pouco de curva de aprendizado, mas eles podem gerar analisadores para qualquer idioma.

Talvez você possa escrever um script simples que converta sua configuração no arquivo XML e depois o leia apenas usando LXML, sopa beatuful ou qualquer outra coisa? E seu conversor pode usar pyparsing ou expressões regulares, por exemplo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top