У меня есть регулярное выражение для идентификации некоторых названных групп. Есть несколько случаев, которые имеют несколько групп с разными шаблонами. Проблема состоит в том, чтобы все названные группы были включены в соответствующие списки. Ограничение состоит в том, что я не могу иметь более одного регулярного выражения, и я не могу вызвать выполнение регулярного выражения более одного раза. Я пробовал следующий код, но он всегда возвращает второй шаблон:
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
Нет необходимости менять ваше регулярное выражение. Вам нужно только изменить способ получения результата из групп захвата.
Поскольку у вас есть несколько групп захвата под тем же именем, чтобы получить все записи, сделанные под этим именем, вам необходимо выполнить цикл 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 позволяет извлекать все захваты группой захвата.
И хотя есть разновидности, позволяющие вам определять одно и то же имя для разных групп захвата, другие вкусы позволяют вам получить доступ к одному из захватов при запросе через имя группы.
В зависимости от специфики, последующие могут работать для ваших нужд, но не являются обобщенным решением:
Regex reg = new Regex(@"((?<n1>(pattern_n1_1|pattern_n1_2)) (?<n2>(pattern_n2_1|pattern_n1_2)) ){2}", RegexOptions.IgnoreCase);
Это будет захватывать немного больше, чем оригинал, поскольку pattern_n1_2 будет пойман как четвертая "группа" в этой версии, например, но не оригинал.