rksoftware

Visual Studio とか C# とかが好きです

コマンドライン引数を雑に扱う

コンソールアプリ、ちょっとした処理を行う際に雑に作ってしまうのが結構いいのですが、何気にコマンドライン引数の解釈コードが面倒です。
それはもう、あらゆる要素をソースコードに書き込んで毎回ソースコード上の値を書き換えてビルドして使うほどに。

というわけで、引数を扱うコードをメモしておきます。まだいろいろ不完全なので今後いじっていきたいコードです。

■ コード

引数を解釈するコード

public static class ArgumentsBuilder
{
    public static (IReadOnlyList<string> parameters, IReadOnlyDictionary<string, string> options) Parse(string[] args)
    {
        List<string> parameters = new();
        Dictionary<string, string> options = new();
        string optionName = "";

        foreach (var arg in args)
        {
            if (string.IsNullOrWhiteSpace(arg))
            {
                continue;
            }

            {
                var pre = arg.First();
                if (new[] { '-', '/' }.Contains(pre))
                {
                    optionName = new string(arg.SkipWhile(c => c == pre).ToArray());
                    options.Add(optionName, "");
                    continue;
                }
            }

            if (string.IsNullOrWhiteSpace(optionName))
            {
                parameters.Add(arg);
                continue;
            }

            options[optionName] = arg;
            optionName = "";
        }

        return (parameters, options);
    }

}

■ 使う方

<実行ファイル名> aparam -a aopt -b bopt bparam /c copt
var parsed = ArgumentsBuilder.ArgumentsBuilder.Parse(args);

// パラメーターは parameters に入ってくる
parsed.parameters.Skip(0).FirstOrDefault(); // aparam
parsed.parameters.Skip(1).FirstOrDefault(); // bparam

// 今回のコードでは、- または / で始まるものがオプション名、オプションは必ず値を持つという前提で解釈しています
{ parsed.options.TryGetValue("a", out var val); } // aopt
{ parsed.options.TryGetValue("b", out var val); } // bopt
{ parsed.options.TryGetValue("c", out var val); } // copt

雑に作るコンソールアプリ用のコピペ元としてはこんな感じでいいでしょうかね。

雑に使う捨て孫ソールアプリを作るなら値を持たないオプションも積極的に使いたいので、後日コードをアップデートしたいと思います。