Pregunta

Quiero analizar una especie de archivo de configuración, así:

[KEY:Value]     
    [SUBKEY:SubValue]

Ahora comencé con un StreamReader, convirtiendo líneas en matrices de caracteres, cuando pensé que debía haber una manera mejor.Por eso te pido, humilde lector, que me ayudes.

Una restricción es que tiene que funcionar en un entorno Linux/Mono (1.2.6 para ser exactos).No tengo la última versión 2.0 (de Mono), así que intente restringir las funciones del lenguaje a C# 2.0 o C# 1.0.

¿Fue útil?

Solución

Lo consideré, pero no voy a usar XML.Voy a escribir esto a mano y editar XML manualmente me duele el cerebro.:')

¿Has mirado YAML?

Obtendrá los beneficios de XML sin todo el dolor y sufrimiento.Se usa ampliamente en la comunidad Ruby para cosas como archivos de configuración, datos de bases de datos preparados previamente, etc.

aquí hay un ejemplo

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

Parece haber una Biblioteca C# aquí, que no he usado personalmente, pero Yaml es bastante simple, así que "¿Qué tan difícil puede ser?" :-)

Yo diría que es preferible inventar su propio formato ad-hoc (y lidiar con errores del analizador)

Otros consejos

Estuve viendo casi este problema exacto el otro día: Este artículo sobre tokenización de cadenas es exactamente lo que necesita.Querrás definir tus tokens como algo como:

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

El artículo hace un buen trabajo al explicarlo.A partir de ahí, empiezas a comer fichas como mejor te parezca.

Consejo profesional:Por un analizador LL(1) (leer:fácil), los tokens no pueden compartir un prefijo.Si usted tiene abc como muestra, no puedes tener ace como muestra

Nota:El artículo le falta el | Personajes en sus ejemplos, simplemente tíralos.

Hay otra biblioteca YAML para .NET que está en desarrollo.En este momento admite la lectura de transmisiones YAML y ha sido probado en Windows y Mono.Actualmente se está implementando soporte de escritura.

Casi siempre es preferible utilizar una biblioteca que crear la suya propia.Aquí hay una lista rápida de puntos "Oh, nunca necesitaré eso/No pensé en eso" que terminarán afectándote más adelante:

  • Personajes que escapan.¿Qué pasa si quieres un:en la clave o ] en el valor?
  • Escapar del personaje de escape.
  • Unicódigo
  • Mezcla de tabulaciones y espacios (consulte los problemas con la sintaxis sensible a los espacios en blanco de Python)
  • Manejo de diferentes formatos de caracteres de retorno
  • Manejo de informes de errores de sintaxis

Como otros han sugerido, YAML parece su mejor opción.

También puedes usar una pila y usar un algoritmo push/pop.Éste coincide con las etiquetas de apertura/cierre.

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";
    }

Probablemente pueda adaptarse para poder leer el contenido de su archivo.Las expresiones regulares también son una buena idea.

Me parece que sería mejor que utilizara un archivo de configuración basado en XML, ya que ya existen clases .NET que pueden leer y almacenar la información con relativa facilidad.¿Hay alguna razón por la que esto no sea posible?

@Bernardo: Es cierto que editar XML manualmente es tedioso, pero la estructura que presentas ya se parece mucho a XML.

Entonces sí, tiene un buen método ahí.

@Gishu

En realidad, una vez que me adapté a los caracteres escapados, mi expresión regular funcionó un poco más lenta que mi analizador recursivo de arriba hacia abajo escrito a mano y eso sin el anidamiento (vinculación de subelementos a sus padres) y el informe de errores que tenía el analizador escrito a mano.

La expresión regular fue un poco más rápida de escribir (aunque tengo un poco de experiencia con analizadores manuales), pero eso sin un buen informe de errores.Una vez que agregas eso, se vuelve un poco más difícil y más largo de hacer.

También encuentro que el analizador escrito a mano es más fácil de entender.Por ejemplo, aquí está un fragmento del 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, ']');
}

Independientemente del formato persistente, usar una expresión regular sería la forma más rápida de análisis.En Ruby probablemente serían unas pocas líneas de código.

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

Estos dos le darían el Valor y el SubValor en el primer grupo.Consulte MSDN sobre cómo hacer coincidir una expresión regular con una cadena.

Esto es algo que todo el mundo debería tener en su gatito.Los días anteriores a Regex parecerían como la Edad del Hielo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top