1

少し調べてみましたが、コンマで区切る程度でうまくいくケースしか見つかりませんでした。このケースは違います。

私の問題を説明するために、小さな例を示します。

JAN 01 00:00:01 <Admin> Action, May have spaces etc.

(これはログ エントリです)

この文字列をいくつかの変数に解析したいと思います。最初のビットは明らかに年を含まない日付です。<> の間にログイン名が表示され、ログ エントリの後ろに表示されます。

構成は次のようになります。

{month} {day} {hour}:{minute}:{second} <{login}> {the_rest}

これにより、すべてをハードコーディングすることなく (分割などを使用して) 変更が可能になります。

ここでは正規表現を使用すると便利だと思いますが、それについてはよくわかりません。また、この場合に使用できるかどうかもまったくわかりません。速度はそれほど重要ではありませんが、これを達成する方法がよくわかりません。

ありがとう、

〜Tgys

4

6 に答える 6

3
string line = "JAN 01 00:00:01 <Admin> Action, May have spaces etc.";
var m = Regex.Match(line, @"(\w{3} \d{2} \d{2}:\d{2}:\d{2}) \<(\w+)\>([\w ]+),([\w ]+)");

var date = DateTime.ParseExact(m.Groups[1].Value,"MMM dd HH:mm:ss",CultureInfo.InvariantCulture);
var user = m.Groups[2].Value;
var action = m.Groups[3].Value;
var text = m.Groups[4].Value;
于 2012-06-20T10:30:25.000 に答える
1

スペース文字で分割して、まだ分割を使用できます。

明らかにあなたの問題は、あなたの「残り」が一緒にとどまるように、あなたが一定量の分割の後にスペースを保持したいということです。

splitのオプションのintパラメーターを使用すると、実行する分割の最大数を指定できるため、探している回避策が提供される場合があります。

http://msdn.microsoft.com/en-us/library/c1bs0eda.aspx

于 2012-06-20T10:28:38.980 に答える
1

正規表現は確かにここで正しいツールです。まず、ハードコードされた正規表現を使用してこのログを解析する方法を見てみましょう。

ハードコードされた正規表現を使用した解析

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}"。同時に、入力を解析するために、ユーザーがこれらの式を自由に組み合わせて一致させることができます。

最終結果を参照してください

于 2012-06-20T10:45:26.227 に答える
1

これを正規表現として使用して、キャプチャされたグループを使用することもできます。

^(?<Month>\w{3})\s(?<Day>\d{2})\s(?<Hour>\d{2}):(?<Min>\d{2}):(?<Sec>\d{2})\s(?<User>\<(\w.+?)\>)(.+)$

正規表現ヒーローのサンプルはこちら.

編集:ユーザー部分を見逃しました。

于 2012-06-20T10:37:47.607 に答える
0

次の正規表現を使用できます。

(?<Month>[A-Z]{3})\s(?<Day>[0-9]{1,2})\s(?<Hour>[0-9]{1,2}):(?<Minute>[0-9]{1,2}):(?<Second>[0-9]{1,2})\s<(?<Login>[^>]+)>(?<Rest>.*)

少し不器用で複雑ですが、以下の例があなたの望むものになることを願っています.

class Foo
{
public string Month { get; set; }
public int Day { get; set; }
public int Hour { get; set; }
public int Minute { get; set; }
public int Second { get; set; }
public string Login { get; set; }
public string Rest { get; set; }
}

string strRegex = @"(?<Month>[A-Z]{3})\s(?<Day>[0-9]{1,2})\s(?<Hour>[0-9]{1,2}):(?<Minute>[0-9]{1,2}):(?<Second>[0-9]{1,2})\s<(?<Login>[^>]+)>(?<Rest>.*)";
RegexOptions myRegexOptions = RegexOptions.None;
Regex myRegex = new Regex(strRegex, myRegexOptions);
string strTargetString = @"JAN 01 00:00:01 <Admin> Action, May have spaces etc. \n";

foreach (Match myMatch in myRegex.Matches(strTargetString))
{
    if (myMatch.Success)
    {
        new Foo
        {
            Month = myMatch.Groups["Month"].Value,
            Day = Convert.ToInt32(myMatch.Groups["Day"].Value),
            Hour = Convert.ToInt32(myMatch.Groups["Hour"].Value),
            Minute = Convert.ToInt32(myMatch.Groups["Minute"].Value),
            Second = Convert.ToInt32(myMatch.Groups["Second"].Value),
            Login = myMatch.Groups["Login"].Value,
            Rest = myMatch.Groups["Rest"].Value
        }
    }
}
于 2012-06-20T10:38:24.043 に答える
0

次の正規表現はそのトリックを行います。

^([A-Z]{3})\s*([0-9]{1,2})\s*([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})\s*<(.+)>\s*(.+)

オンライン正規表現ビルダーを使用してテストしました。

キャプチャされた 7 つのグループが返されます。

  • グループ 1: ([AZ]{3}): 月
  • グループ 2: ([0-9]{1,2}): 日
  • グループ 3: ([0-9]{1,2}): 時間
  • グループ 4: ([0-9]{1,2}): 分
  • グループ 5: ([0-9]{1,2}): 2 番目
  • グループ 6: (.+): ユーザー名
  • グループ 7: (.+): 残り
于 2012-06-20T10:41:00.420 に答える