. NET Core - Регулярные выражения - Доступ к захватам внутри совпавшей строки текста - PullRequest
2 голосов
/ 22 февраля 2020

Я пытаюсь выучить регулярные выражения с. net core. В частности, я пытаюсь использовать их для анализа списка встроенных ресурсов в сборке, как показано ниже.

Шаблон регулярного выражения

^([\w\._])*((?<create>\.Postgres.Create\.)|(?<drop>\.Postgres.Drop\.)([\w\._]))*$

Пример текста, сгенерированного из списка встроенных ресурсов

Mynamespace.Postgresql.Create.select_course_units.sql
Mynamespace.Postgresql.Drop.drop_select_course_units.sql
Mynamespace.Postgresql.Create.select_units.sql
Mynamespace.Postgresql.Drop.drop_select_units.sql
...

Регулярное выражение имеет две именованные группы захвата для Postgres .Create и Postgres .Drop захватывает, соответственно. Мое регулярное выражение находит оба совпадения, но в записях ничего не сохраняется для создания или удаления групп. Можно ли заставить его хранить записи, чтобы можно было определить, содержит ли совпадение создание или отбрасывание?

public void ReadCreateStoredProcedures()
{
    const string pattern = @"^([\w\._])*((?<create>\.Postgres.Create\.)|(?<drop>\.Postgres.Drop\.)([\w\._]))*$";  
    Regex rx = new Regex(pattern, RegexOptions.Compiled | RegexOptions.Multiline);

    string[] resNames = typeof(CourseContext).Assembly.GetManifestResourceNames();
    string text = string.Join("\n",resNames);

    MatchCollection matches = rx.Matches(text);
    foreach(Match match in matches)
    {
        Console.WriteLine($"Matched{match.Value}");
        GroupCollection col = match.Groups;

        int lC = col["create"].Length;
        int lD = col["drop"].Length;

        Console.WriteLine($"Total Create Captures : {lC}");
        Console.WriteLine($"Total Drop Captures : {lD}");

        foreach(var capture in col["create"].Captures)
        {
            Console.WriteLine($"Create Capture :: {@capture}");
        }
        foreach (var capture in col["drop"].Captures)
        {
            Console.WriteLine($"Drop Capture :: {@capture}");
        }
    }
}

1 Ответ

1 голос
/ 22 февраля 2020

В вашем шаблоне вы не получите значения в именованных группах захвата, потому что эта часть в начале ([\w\._])* сначала будет полностью соответствовать до конца строки.

Вы получите 1 группа захвата (не именованная группа захвата) с одним символом, который будет последним символом строки, как при повторении захваченной группы, группа будет содержать значение последней итерации.

Далее следует необязательная часть ((?<create>\.Postgres.Create\.))*$. Поскольку это необязательно, шаблон может утверждать следующий конец строки, и именованная группа захвата не содержит значения.

Примечание , что \w также соответствует подчеркиванию, и вы не не нужно экранировать точку в классе символов


Если вы хотите захватить оба значения, начиная с Postgresql, вы можете использовать группу захвата 2, например, такую:

^\w+\.(?:(?<create>Postgresql\.Create(?:\.\w+)+)|(?<drop>Postgresql\.Drop(?:\.\w+)+))$

Пояснение

  • ^ Начало строки
  • \w+\. Соответствие 1+ словам символов
  • (?: Не группа захвата
    • (?<create> Именованная группа create
      • Postgresql\.Create(?:\.\w+)+ Match Postgresql.Create and repeat matching a .` и символы 1+ слов
    • ) Закрыть группу
    • | Или
    • (?<drop> Именованная группа drop
      • Postgresql\.Drop(?:\.\w+)+ То же, что и выше для Postgresql .Drop
    • ) Именованная группа drop
  • ) Закрыть группу без захвата
  • $ Конец строки

. NET regex demo (нажмите на вкладку Table)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...