Pergunta

Eu quero analisar um tipo de arquivo de configuração, assim:

[KEY:Value]     
    [SUBKEY:SubValue]

Agora comecei com um StreamReader, convertendo linhas em matrizes de caracteres, quando percebi que deveria haver uma maneira melhor.Por isso peço a você, humilde leitor, que me ajude.

Uma restrição é que ele deve funcionar em um ambiente Linux/Mono (1.2.6 para ser exato).Não tenho a versão 2.0 mais recente (do Mono), então tente restringir os recursos da linguagem para C# 2.0 ou C# 1.0.

Foi útil?

Solução

Eu considerei isso, mas não vou usar XML.Vou escrever essas coisas à mão, e editar XML manualmente faz meu cérebro doer.:')

Você já olhou YAML?

Você obtém os benefícios do XML sem toda a dor e sofrimento.É usado extensivamente na comunidade Ruby para coisas como arquivos de configuração, dados de banco de dados pré-preparados, etc.

aqui está um exemplo

customer:
  name: Orion
  age: 26
  addresses:
    - type: Work
      number: 12
      street: Bob Street
    - type: Home
      number: 15
      street: Secret Road

Parece haver um Biblioteca C# aqui, que não usei pessoalmente, mas a YAML é bem simples, então "quão difícil pode ser?" :-)

Eu diria que é preferível inventar seu próprio formato ad-hoc (e lidar com bugs do analisador)

Outras dicas

Eu estava olhando quase exatamente para esse problema outro dia: Este artigo na tokenização de strings é exatamente o que você precisa.Você desejará definir seus tokens como algo como:

@"(?&ltlevel>\s) | " +
@"(?&ltterm>[^:\s]) | " +
@"(?&ltseparator>:)"

O artigo explica muito bem.A partir daí, você simplesmente começa a consumir fichas como achar melhor.

Dica:Para um Analisador LL(1) (ler:fácil), os tokens não podem compartilhar um prefixo.Se você tem abc como um token, você não pode ter ace como um token

Observação:O artigo está faltando o | Personagens em seus exemplos, basta jogá -los.

outra biblioteca YAML para .NET que está em desenvolvimento.No momento, ele suporta a leitura de fluxos YAML e foi testado em Windows e Mono.O suporte de gravação está sendo implementado atualmente.

Usar uma biblioteca é quase sempre preferível a criar a sua própria.Aqui está uma lista rápida de pontos do tipo "Oh, nunca vou precisar disso/não pensei nisso" que acabarão incomodando você mais tarde:

  • Personagens escapando.E se você quiser um:na chave ou ] no valor?
  • Escapando do caractere de escape.
  • Unicode
  • Mistura de tabulações e espaços (veja os problemas com a sintaxe sensível a espaços em branco do Python)
  • Lidando com diferentes formatos de caracteres de retorno
  • Tratamento de relatórios de erros de sintaxe

Como outros sugeriram, o YAML parece ser sua melhor aposta.

Você também pode usar uma pilha e um algoritmo push/pop.Este corresponde às tags de abertura/fechamento.

public string check()
    {
        ArrayList tags = getTags();


        int stackSize = tags.Count;

        Stack stack = new Stack(stackSize);

        foreach (string tag in tags)
        {
            if (!tag.Contains('/'))
            {
                stack.push(tag);
            }
            else
            {
                if (!stack.isEmpty())
                {
                    string startTag = stack.pop();
                    startTag = startTag.Substring(1, startTag.Length - 1);
                    string endTag = tag.Substring(2, tag.Length - 2);
                    if (!startTag.Equals(endTag))
                    {
                        return "Fout: geen matchende eindtag";
                    }
                }
                else
                {
                    return "Fout: geen matchende openeningstag";
                }
            }
        }

        if (!stack.isEmpty())
        {
            return "Fout: geen matchende eindtag";
        }            
        return "Xml is valid";
    }

Provavelmente você pode se adaptar para poder ler o conteúdo do seu arquivo.Expressões regulares também são uma boa ideia.

Parece-me que seria melhor usar um arquivo de configuração baseado em XML, pois já existem classes .NET que podem ler e armazenar as informações para você com relativa facilidade.Existe uma razão para que isso não seja possível?

@Bernardo: É verdade que editar XML manualmente é entediante, mas a estrutura que você está apresentando já se parece muito com XML.

Aí sim, tem um bom método aí.

@Gishu

Na verdade, uma vez que eu acomodei os caracteres de escape, meu regex funcionou um pouco mais lento do que meu analisador recursivo escrito à mão de cima para baixo e isso sem o aninhamento (vinculando subitens aos seus pais) e erro ao relatar que o analisador escrito à mão tinha.

O regex foi um pouco mais rápido de escrever (embora eu tenha um pouco de experiência com analisadores manuais), mas isso sem um bom relatório de erros.Depois de adicionar isso, fica um pouco mais difícil e demorado de fazer.

Também acho o analisador escrito à mão mais fácil de entender a intenção.Por exemplo, aqui está um trecho do código:

private static Node ParseNode(TextReader reader)
{
    Node node = new Node();
    int indentation = ParseWhitespace(reader);
    Expect(reader, '[');
    node.Key = ParseTerminatedString(reader, ':');
    node.Value = ParseTerminatedString(reader, ']');
}

Independentemente do formato persistente, usar um Regex seria a maneira mais rápida de análise.Em Ruby provavelmente seriam algumas linhas de código.

\[KEY:(.*)\] 
\[SUBKEY:(.*)\]

Esses dois forneceriam o valor e o subvalor no primeiro grupo.Confira o MSDN sobre como combinar um regex com uma string.

Isso é algo que todos deveriam ter em seus gatinhos.Os dias pré-Regex pareceriam a Era do Gelo.

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