Как иметь две именованные группы с одинаковыми именами в .net регулярных выражений?

1

У меня есть регулярное выражение для идентификации некоторых названных групп. Есть несколько случаев, которые имеют несколько групп с разными шаблонами. Проблема состоит в том, чтобы все названные группы были включены в соответствующие списки. Ограничение состоит в том, что я не могу иметь более одного регулярного выражения, и я не могу вызвать выполнение регулярного выражения более одного раза. Я пробовал следующий код, но он всегда возвращает второй шаблон:

        Regex reg = new Regex(@"(?<n1>pattern_n1_1) (?<n2>pattern_n2_1) (?<n1>pattern_n1_2) (?<n2>pattern_n1_2)", RegexOptions.IgnoreCase);

        String str = "pattern_n1_1 pattern_n2_1 pattern_n1_2 pattern_n1_2";

        List<String> matchedText = new List<string>();
        List<String> string_n1 = new List<string>();
        List<String> string_n2 = new List<string>();

        MatchCollection mc = reg.Matches(str);
        if (mc != null)
        {
            foreach (Match m in mc)
            {
                matchedText.Add(m.Value.Trim());
                string_n1.Add(m.Groups["n1"].Value);
                string_n2.Add(m.Groups["n2"].Value);
            }
        }

Здесь список string_n1 и string_n2 имеет по одному элементу. string_n1 имеет " string_n1 ", а string_n2 имеет " string_n2 ". Тем не менее, мне нужно, чтобы "pattern_n1_1" и "pattern_n1_2" были в string_n1 И оба "pattern_n2_1" и "pattern_n2_2" были в string_n2

  • 0
    не решение, но я нахожу этот инструмент очень удобным, когда дело доходит до отладки строк регулярных выражений. Возможно, это может помочь вам.
  • 1
    @NickOtten: Не предлагайте регулярное выражение в вопросе C #. Это инструмент для JS RegExp. Для .NET regex есть regexhero и regexstorm, также regexplanet, хотя по моему опыту, regexstorm является лучшим в отображении всех возможностей .NET regex.
Показать ещё 3 комментария
Теги:

2 ответа

2
Лучший ответ

Нет необходимости менять ваше регулярное выражение. Вам нужно только изменить способ получения результата из групп захвата.

Поскольку у вас есть несколько групп захвата под тем же именем, чтобы получить все записи, сделанные под этим именем, вам необходимо выполнить цикл Capture in Groups["n1"].Captures вместо того, чтобы получать доступ к одному захвату с помощью Groups["n1"].Value.

MatchCollection mc = reg.Matches(str);
if (mc != null)
{
    foreach (Match m in mc)
    {
        matchedText.Add(m.Value.Trim());

        foreach (Capture c in m.Groups["n1"].Captures) {
            string_n1.Add(c.Value);
        }

        foreach (Capture c in m.Groups["n2"].Captures) {
            string_n2.Add(c.Value);
        }
    }
}

Демо на идеон

Эта функция, насколько мне известно, уникальна для.NET Regex API. Ни один из других вариантов не предлагает API для прохождения всех совпадений группы повторного захвата:

^\w+(?: (\w+))+$

Другие ароматы возвращают только последний захват для группы захвата 1 в приведенном выше примере. .NET позволяет извлекать все захваты группой захвата.

И хотя есть разновидности, позволяющие вам определять одно и то же имя для разных групп захвата, другие вкусы позволяют вам получить доступ к одному из захватов при запросе через имя группы.

Справка

  • 0
    Спасибо за подробный ответ. Код работает как положено.
0

В зависимости от специфики, последующие могут работать для ваших нужд, но не являются обобщенным решением:

Regex reg = new Regex(@"((?<n1>(pattern_n1_1|pattern_n1_2)) (?<n2>(pattern_n2_1|pattern_n1_2)) ){2}", RegexOptions.IgnoreCase);

Это будет захватывать немного больше, чем оригинал, поскольку pattern_n1_2 будет пойман как четвертая "группа" в этой версии, например, но не оригинал.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню