0

私は完璧に機能する正規表現を持っています。

^SENT KV(?<singlelinedata> L(?<line>[1-9]\d*) (?<measureline>\d+)(?: (?<samplingpoint>\d+))+)+$

私の入力文字列は次のようになります。

SENT KV L1 123 1 2 3 L2 456 4 5 6

唯一の質問は次のとおりです。グループ「サンプリングポイント」のすべてのキャプチャのコンテキストを取得するにはどうすればよいですか?

このグループには 6 つのキャプチャが含まれていますが、コンテキスト情報も必要です。グループ「singlelinedata」の最初のキャプチャには 3 つのキャプチャがあり、2 番目のキャプチャには 3 つのキャプチャがあります。この情報を取得する方法は?

グループのキャプチャには、含まれるグループのすべてのキャプチャを含むプロパティが含まれていません。

文字列全体に一致する単一の正規表現を記述し、2 番目の正規表現を実行してすべての「singlelinedata」キャプチャを解析できることを知っています。

指定された正規表現で機能する方法を探しています。

誰かが私を助けてくれることを願っています。

4

4 に答える 4

0

多くのインデックス マッチングを実行せずに単一の正規表現を維持する 1 つの方法は、キャプチャ グループをすべて同じ名前に変更することです。ネストされたキャプチャは実際には最初にスタックにプッシュされるため、次のような配列になります。

["1", "123", "1", "2", "3", "L1 123 1 2 3", "2", "456", "4", "5", "6", "L2 456 4 5 6"]

次に、L を含むキャプチャが見つかったときに結果をグループに分割し、各グループからデータを引き出すのは、LINQ の狂気の問題です。

var regex = new Regex(@"^SENT KV(?<singlelinedata> L(?<singlelinedata>[1-9]\d*) (?<singlelinedata>\d+)(?: (?<singlelinedata>\d+))+)+$");
var matches = regex.Matches("SENT KV L1 123 1 2 3 L2 456 4 5 6 12 13 L3 789 7 8 9 10");
var singlelinedata = matches[0].Groups["singlelinedata"];

string groupKey = null;
var result = singlelinedata.Captures.OfType<Capture>()
    .Reverse()
    .GroupBy(key => groupKey = key.Value.Contains("L") ? key.Value : groupKey, value => value.Value)
    .Reverse()
    .Select(group => new { key = group.Key, data = group.Skip(1).Reverse().ToList() })
    .Select(item => new { line = item.data.First(), measureline = item.data.Skip(1).First(), samplingpoints = item.data.Skip(2).ToList() })
    .ToList();
于 2013-10-22T09:09:09.320 に答える
0

Markus Jarderotの回答に基づいて、キャプチャを取得し、指定されたキャプチャ内のそのグループのすべてのキャプチャを返すグループの拡張メソッドを作成しました。

拡張メソッドは次のようになります。

    public static IEnumerable<Capture> CapturesWithin(this Group source, Capture captureContainingGroup)
    {
        var lowerIndex = captureContainingGroup.Index;
        var upperIndex = lowerIndex + captureContainingGroup.Length - 1;

        foreach (var capture in source.Captures.Cast<Capture>())
        {
            if (capture.Index < lowerIndex)
            {
                continue;
            }

            if (capture.Index > upperIndex)
            {
                break;
            }

            yield return capture;
        }
    }

このメソッドの使用法:

foreach (var capture in match.Groups["singlelinedata"].Captures.Cast<Capture>())
{
    var samplingpoints = match.Groups["samplingpoint"].CapturesWithin(capture).ToList();
    ...
于 2013-10-22T09:41:57.233 に答える
0

正規表現 API には「サブグループ」という概念はありません。samplingpointグループは複数のキャプチャを持つことができますが、どれがどのに属しているかはわかりませんline

唯一のオプションは、文字インデックスを使用して自分で計算することです。

于 2013-10-22T07:35:24.197 に答える
0
void Main()
{
    string data = @"SENT KV L1 123 1 2 3 L2 456 4 5 6";
    Parse(data).Dump();
}

public class Result
{
    public int Line;
    public int MeasureLine;
    public List<int> SamplingPoints;
}

private Regex pattern = new Regex(@"^SENT KV(?<singlelinedata> L(?<line>[1-9]\d*) (?<measureline>\d+)(?: (?<samplingpoint>\d+))+)+$", RegexOptions.Multiline);

public IEnumerable<Result> Parse(string data)
{
    foreach (Match m in pattern.Matches(data))
    {
        foreach (Capture c1 in m.Groups["singlelinedata"].Captures)
        {
            int lineStart = c1.Index;
            int lineEnd = c1.Index + c1.Length;

            var result = new Result();
            result.Line = int.Parse(m.Groups["line"].CapturesWithin(c1).First().Value);
            result.MeasureLine = int.Parse(m.Groups["measureline"].CapturesWithin(c1).First().Value);

            result.SamplingPoints = new List<int>();
            foreach (Capture c2 in m.Groups["samplingpoint"].CapturesWithin(c1))
            {
                result.SamplingPoints.Add(int.Parse(c2.Value));
            }

            yield return result;
        }
    }
}

public static class RegexExtensions
{
    public static IEnumerable<Capture> CapturesWithin(this Group group, Capture capture)
    {
        foreach (Capture c in group.Captures)
        {
            if (c.Index < capture.Index) continue;
            if (c.Index >= capture.Index + capture.Length) break;

            yield return c;
        }
    }
}

編集:の拡張メソッドとして書き直されましたGroup

于 2013-10-22T08:49:07.720 に答える