Группы захвата регулярного выражения - PullRequest
0 голосов
/ 07 января 2019

Со следующим регулярным выражением:

InitValue\((\w*)\)

и тестовая строка:

InitValue(Input1)

Я получаю следующий результат:

Full match: InitValue(Input1)
Group1: Input1

Со следующим регулярным выражением:

InitValue\((\w*)\s*,\s*(\w*)\)

и тестовая строка:

InitValue(Input1, Input2)

Я получаю:

Full match: InitValue(Input1, Input2)
Group1: Input1
Group2: Input2

Теперь я хотел бы захватить любое количество аргументов для метода InitValue. Количество аргументов для InitValue неизвестно.

Full match: InitValue(Input1, Input2, ..., Inputn)
Group1: Input1
Group2: Input2
....
Groupn: Inputn

Конечно, я не могу повторить следующий шаблон в своем регулярном выражении, так как заранее не знаю количество аргументов:

\s*,\s*(\w*)

Как написать регулярное выражение, которое выводит n чисел групп захвата?

Я использую регулярное выражение в C # -коде (Regex, Match) ...

Ответы [ 4 ]

0 голосов
/ 08 января 2019

.NET поддерживает бесконечный взгляд назад (?<=. Вместо того, чтобы получать группы, другим вариантом может быть получение совпадений:

(?<=\bInitValue\([^()]*)[^, ]+(?=[^()]*\))

Объяснение

  • (?<= Позитивный взгляд сзади, проверьте, что слева соответствует:
    • \bInitValue\([^()]* Соответствует границе слова, InitValue(, а затем 0+ раз, но не ( или )
  • ) Закрыть положительный взгляд за спиной
  • [^, \t]+ Класс отрицательных символов, соответствует 1+ раз, без пробела или запятой
  • (?= Позитивный взгляд, чтобы проверить правильность совпадений:
    • [^()]*\) Совпадение 0+ раз, а не ( или ), затем совпадение )
  • ) Закрыть позитивный прогноз

Например:

string pattern = @"(?<=\bInitValue\([^()]*)[^, ]+(?=[^()]*\))";
string str = "InitValue(Input1, Input2, Input3)";            
foreach (Match m in Regex.Matches(str, pattern))
{
    Console.WriteLine(m.Value);
}

Результат

Input1
Input2
Input3

См. Демоверсию Regex | C # демо

0 голосов
/ 07 января 2019

Это можно сделать в .NET - вы используете один захват Group, а затем получаете доступ к коллекции Captures группы, чтобы увидеть все захваченные элементы, а не только окончательный Value.

Вам нужно написать регулярное выражение, которое может повторять группу сопоставления аргументов, что-то вроде

InitValue\((?:(\w+)\s*(?:,(?!\s*\))|(?=\s*\)))\s*)*\)

Поэкспериментируйте с Debuggex Demo , чтобы он соответствовал тому, что вы хотите.

0 голосов
/ 07 января 2019
static void GetParams()
{
    int x = 0;
    var strings = new[]
    {
        "InitValue()",
        "InitValue(Input1)",
        "InitValue(Input1, Input2, Input3, Input4)"
    };

    var pattern = @"(\w+)\((?:(\w+)(?:,?\s*))*\)";

    foreach (var s in strings)
    {
        WriteLine($"String: '{s}'");
        var match = Regex.Match(s, pattern);
        if (match.Success)
        {
            WriteLine($"\tMethod: '{match.Groups[1].Value}'");
            WriteLine("\tParameters:");
            var captures = match.Groups[2].Captures;
            if (captures.Count > 0)
            {
                x = 0;
                foreach (Capture capture in captures)
                {
                    WriteLine($"\t\tParam {++x}: '{capture.Value}'");
                }
            }
            else
            {
                WriteLine("\t\tNo params found.");
            }

            WriteLine();
        }

        else
            WriteLine("No matches found.");
    }
}

/*
Output:

String: 'InitValue()'
        Method: 'InitValue'
        Parameters:
                No params found.

String: 'InitValue(Input1)'
        Method: 'InitValue'
        Parameters:
                Param 1: 'Input1'

String: 'InitValue(Input1, Input2, Input3, Input4)'
        Method: 'InitValue'
        Parameters:
                Param 1: 'Input1'
                Param 2: 'Input2'
                Param 3: 'Input3'
                Param 4: 'Input4'
*/
0 голосов
/ 07 января 2019

Не позволяйте никому говорить вам, что это невозможно, а что нет

enter image description here

Тебе придется немного потрогать, но я думаю, что это поможет тебе = D.

Редактировать, отвечая на ваш вопрос. b.Count даст вам количество совпадений.
Редактировать 2, я публикую картинку, чтобы показать отладочную информацию. Но вот код для сибариста.

string bar = "test, othertest";
Regex reg = new Regex(@"[\w]+");

MatchCollection b = reg.Matches(bar);

string b1 = b[0].Value;
string b2 = b[1].Value;

int numberGroups = b.Count;

Редактировать 3, как указано в комментарии, это полное решение, вам нужно очистить InitValue (*) с другой Regex или с Substring

string input = "InitValue(test, othertest, bleh, blehTest, foo)";

Regex regArgs = new Regex(@"(?:InitValue\()(.*)(?:\))");
Match matchArgs = regArgs.Match(input);

string valueArgs = matchArgs.Groups[1].Value;

Regex reg = new Regex(@"[\w]+");

MatchCollection b = reg.Matches(valueArgs);

string b1 = b[0].Value;
string b2 = b[1].Value;

int numberGroups = b.Count;
...