正規表現は確かにここで正しいツールです。まず、ハードコードされた正規表現を使用してこのログを解析する方法を見てみましょう。
ハードコードされた正規表現を使用した解析
var str = "JAN 01 00:00:01 <Admin> Action, May have spaces etc.";
var re = new Regex("^" +
@"(?<month>(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))" +
" " +
@"(?<day>\d+)" +
" " +
@"(?<hour>\d+)" +
":" +
@"(?<the_rest>.*)" +
"$");
var match = re.Match(str);
ここで行ったことは、名前付きキャプチャグループを使用して正規表現を1つずつ作成することです。簡潔にするためにすべての関連情報を収集したわけではなく、各グループのコンテキストで有効な入力を検討するのにあまり時間をかけませんでした(たとえば、有効な日ではありませんが、day
一致999
します)。これはすべて後で来る可能性があります。今のところ、実際の動作を確認してください。
事前定義された部分から正規表現を構築する
次のステップは、各キャプチャグループの定義を辞書にうまく引き出すことです。
var groups = new Dictionary<string, string>
{
{ "month", "(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)" },
{ "day", @"\d+" },
{ "hour", @"\d+" },
{ "the_rest", ".*" },
};
これを考えると、同じ正規表現を次のように作成できます。
var re = new Regex("^" +
string.Format("(?<month{0}>)", groups["month"]) +
" " +
string.Format("(?<day{0}>)", groups["day"]) +
" " +
string.Format("(?<hour{0}>)", groups["hour"]) +
":" +
string.Format("(?<the_rest{0}>)", groups["the_rest"]) +
"$");
OK、これは動的に構築できるもののように見え始めています。
ユーザー指定の仕様に基づいて正規表現を作成する
次のような仕様から構築したいとします。
"{month} {day} {hour}:{the_rest}"
これを行う方法?別の正規表現で!具体的にはRegex.Replace
、関数の結果で一致を置き換えることができるのオーバーロードを使用します。
var format = "{month} {day} {hour}:{the_rest}";
var result = Regex.Replace(format, @"\{(\w+)\}", m => groups[m.Groups[1].Value]);
戻ってくる前に、これを実際に見てください。
正規表現を使用して入力を解析する
この時点で、フォーマット仕様を渡して、このフォーマットに基づく入力に一致する正規表現を取得できます。何が残っていますか?正規表現を入力に一致させた結果を「動的」構造に変換するには、次のようにします。
var format = "{month} {day} {hour}:{the_rest}";
var re = Regex.Replace(format,
@"\{(\w+)\}",
m => string.Format("(?<{0}>{1})", m.Groups[1].Value, groups[m.Groups[1].Value]));
var regex = new Regex("^" + re + "$", RegexOptions.ExplicitCapture);
var match = regex.Match(str);
最終結果を引き出す
この時点で:
match.Success
動的に構築された式が入力と一致するかどうかをテストできます
- 繰り返して
regex.GetGroupNames()
、解析に使用されるグループの名前を取得できます
- 繰り返して
match.Groups
、各グループの解析結果を取得できます
それでは、それらを辞書に入れましょう。
var results = regex.GetGroupNames().ToDictionary(n => n, n => match.Groups[n].Value);
成功!
Parse
これで、これを可能にするメソッドを作成できます。
var input = "JAN 01 00:00:01 <Admin> Action, May have spaces etc.";
var format = "{month} {day} {hour}:{the_rest}";
var results = Parse(input, format);
Parse
は、などの式を認識します(ただし、ユーザーが変更することはできません)"{month}"
。同時に、入力を解析するために、ユーザーがこれらの式を自由に組み合わせて一致させることができます。
最終結果を参照してください。