2013-02-14 3 views
0

Рассмотрим это регулярное выражение:Якорь и группа повторения

(?:([A-Z][0-9a-z]*)+?) 

При применении aplied к строке "A1BaaC2d", это дает мне 3 группы: "A1", "Баа", и "C2D"

Однако, когда я применяю якорь начала и конца строки, т. Е.^(?: ([AZ] [0-9a-z] *) +?) $, Он больше не работает правильно. Я предполагаю, что это проблема, связанная с ссылкой (добавьте дополнительную группу, которую я пробовал как не захватывающий, так и атомный). Но я не могу это исправить. Как получить мои группы и проверить, что общая строка не содержит никаких ведущих или завершающих символов.

FYI это .net регулярное выражение.

+0

Валидация работает правильно. Нет проблем с вашим регулярным выражением. Не уверен, но я думаю, что вы должны получить группу отдельно от проверки. – nhahtdh

+1

Можете вы показать нам, как вы его использовали? Я не могу поверить, что одна группа дает вам три захватывающих матча. – Bergi

+0

@Bergi: Я думаю, что он говорит о трех последовательных * совпадениях * всего регулярного выражения; см. мой ответ. –

ответ

3

Давайте стричь это вниз к основам:

([A-Z][0-9a-z]*)+ 

(я избавилась от внешнего, не-захвата группы, потому что это был не имеющий никакого влияния на результаты, и я временно удалил ? из квантора .) У вас есть регулярное выражение с одной группой захвата. Подвыражение внутри этой группы должно совпадать хотя бы один раз из-за квантора +, но кванторы по умолчанию жадные, поэтому он фактически соответствует вашему вводу три раза. Вот разбивка:

Match 1 = A1BaaC2d 
Group 1 = C2d 
Capture 1 = A1 
Capture 2 = Baa 
Capture 3 = C2d 

(«Группа 1» относится к заключительному значение захваченного этой группы в большинстве регулярных выражений вкусов/инструментов, это вся информация, вы получите, .NET уникален тем, что это. позволяешь разбить весь промежуточный Captures а)

Однако вы использовали нежадную версию квантора, +?:.

([A-Z][0-9a-z]*)+? 

Он по-прежнему должен соответствовать (и захвату) [A-Z][0-9a-z]* хотя бы один раз, но теперь он останавливается прямо там, если что-то не заставляет его продолжать. Ничто не делает, так что вы получите три отдельных Матчи, каждая из которых содержит один Capture:

Match 1 = A1 
Group 1 = A1 
Capture 1 = A1 

Match 1 = Baa 
Group 1 = Baa 
Capture 1 = Baa 

Match 1 = C2d 
Group 1 = C2d 
Capture 1 = C2d 

Затем вы добавили якоря:

^([A-Z][0-9a-z]*)+?$ 

Теперь каждый матч должен начаться в начале строка и конец в конце строки. Чтобы достичь этого, движок регулярных выражений перекрывает не-алчность в +?, и вы вернулись к одному матчу с тремя Протоколируется:

Match 1 = A1BaaC2d 
Group 1 = C2d 
Capture 1 = A1 
Capture 2 = Baa 
Capture 3 = C2d 

Ниже окончательный вариант кода я использовал для создания этого вывода. Имейте в виду, что вам действительно не нужно использовать неживое регулярное выражение; ^([A-Z][0-9a-z]*)+$ будет работать так же хорошо.

static void Main() 
{ 
    string source = "A1BaaC2d"; 
    Regex r = new Regex(@"^([A-Z][0-9a-z]*)+?$"); 
    foreach (Match m in r.Matches(source)) 
    { 
    int x = 1; 
    Console.WriteLine(@"Match {0} = {1}", x++, m.Value); 
    Console.WriteLine(@"Group 1 = {0}", m.Groups[1]); 
    int y = 1; 
    foreach (Capture c in m.Groups[1].Captures) 
    { 
     Console.WriteLine(@"Capture {0} = {1}", y++, c.Value); 
    } 
    Console.WriteLine(); 
    } 
} 
+0

Отличный ответ, и, честно говоря, я бы не стал его использовать без вашего опубликованного примера, так как вы используете регулярное выражение, с которого я начал. Я полностью забыл о классе «Capture», который не поддерживается большинством тестировщиков регулярных выражений, которые я использовал, и это привело меня к неправильной дороге. –

Смежные вопросы