9

次のように、構成ファイルの一種を解析したい:

[KEY:Value]     
    [SUBKEY:SubValue]

行を文字配列に変換することから始めましたStreamReaderが、もっと良い方法があるはずだと思いました。ですから、謙虚な読者の皆さん、私を助けてください。

1 つの制限は、Linux/Mono 環境 (正確には 1.2.6) で動作する必要があることです。(Mono の) 最新の 2.0 リリースを持っていないので、言語機能を C# 2.0 または C# 1.0 に制限してみてください。

4

8 に答える 8

12

検討しましたが、XML を使用するつもりはありません。私はこのようなものを手で書くつもりであり、XML を手で編集すると頭が痛くなります。:')

YAMLを見たことがありますか?

XML の利点は、痛みや苦しみをまったく感じずに得られます。構成ファイル、事前に準備されたデータベースデータなどのために、Ruby コミュニティで広く使用されています。

これが例です

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

ここに C# ライブラリがあるようですが、個人的には使用していませんが、yaml は非常に単純なので、「どれくらい難しいのでしょうか?」:-)

独自のアドホック形式を発明する (およびパーサーのバグに対処する) よりも望ましいと思います。

于 2008-08-17T22:39:50.833 に答える
4

私は先日、まさにこの問題を見ていました。文字列のトークン化に関するこの記事はまさにあなたが必要としているものです。トークンを次のように定義する必要があります。

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

記事はそれを説明するのにかなり良い仕事をしています. そこから、必要に応じてトークンを使い始めます。

プロのヒント: LL(1) パーサー(読み取り: 簡単) の場合、トークンはプレフィックスを共有できません。トークンとして持っている場合、トークンとしてabc持つことはできませんace

注: 記事には | がありません。その例の文字は、それらを投げ込むだけです.

于 2008-08-17T22:25:55.433 に答える
1

開発中の.NET用の別のYAMLライブラリがあります。現在、YAMLストリームの読み取りをサポートしており、WindowsとMonoでテストされています。書き込みサポートは現在実装されています。

于 2008-08-26T23:33:36.833 に答える
1

ライブラリを使用することは、ほとんどの場合、自分で作成するよりも望ましいことです。これは、後であなたを噛むことになる「ああ、私はそれを必要としない/私はそれについて考えていなかった」ポイントの簡単なリストです。

  • 文字のエスケープ。キーに : または値に ] が必要な場合はどうすればよいでしょうか?
  • エスケープ文字のエスケープ。
  • ユニコード
  • タブとスペースの混合 (Python の空白に敏感な構文の問題を参照)
  • 異なる戻り文字形式の処理
  • 構文エラー報告の処理

他の人が示唆しているように、YAML が最善の策のようです。

于 2008-08-18T00:35:36.310 に答える
0

@ギス

実際、エスケープ文字に対応すると、正規表現の実行速度は、手書きのトップダウン再帰パーサーよりもわずかに遅くなります。これには、ネスト(サブアイテムを親にリンクする)や、手書きのパーサーのエラーレポートがありません。

正規表現は書くのが少し速かったですが(私はハンドパーサーの経験が少しありますが)、それは良いエラー報告がありません。これを追加すると、実行が少し難しくなり、長くなります。

また、手書きのパーサーはその意図を理解しやすいと思います。たとえば、コードのスニペットは次のとおりです。

private static Node ParseNode(TextReader reader)
{
    Node node = new Node();
    int indentation = ParseWhitespace(reader);
    Expect(reader, '[');
    node.Key = ParseTerminatedString(reader, ':');
    node.Value = ParseTerminatedString(reader, ']');
}
于 2008-08-18T07:52:29.237 に答える
0

情報を比較的簡単に読み取って保存できる .NET クラスが既に存在するため、XML ベースの構成ファイルを使用する方がよいと思われます。これが不可能な理由はありますか?

@バーナード: XML を手作業で編集するのは面倒ですが、提示している構造はすでに XML と非常によく似ています。

それから、はい、そこに良い方法があります。

于 2008-08-17T22:12:15.740 に答える
0

スタックを使用して、プッシュ/ポップ アルゴリズムを使用することもできます。これは、開始/終了タグに一致します。

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

ファイルの内容を読み取ることができるように、おそらく適応できます。正規表現も良い考えです。

于 2008-08-17T22:12:19.267 に答える
-1

永続化された形式に関係なく、正規表現を使用するのが最速の解析方法です。ルビーでは、おそらく数行のコードになります。

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

これらの2つは、最初のグループのValueとSubValueを取得します。正規表現を文字列と照合する方法については、MSDNを確認してください。

これは誰もが子猫に持っているべきものです。正規表現前の日は氷河期のように見えます。

于 2008-08-18T07:22:11.950 に答える