2009-12-01 2 views
5

Это мой первый опыт работы с C# и частью моего ограниченного опыта с регулярными выражениями, и у меня возникли проблемы с захватом первого совпадения в определенном выражении. Я считаю, что следующий пример сделает его более понятным, чем слова в описании того, что я хочу делать.Захват первого совпадения с регулярным выражением (C#)

Match extractor = (new Regex(@".*\d(?<name>.*)\d.*")).Match("This hopefully will pick up 1Bob9error1 as a name"); 
     Console.WriteLine(extractor.Groups["name"]); 

Я хотел бы, чтобы это выражение напечатало «Боб» вместо «ошибки».

У меня есть подозрение, что это как-то связано с? перед соответствующей группой, но я не совсем уверен, какая операция? выполняет в этом конкретном случае. Объяснение наряду с некоторой помощью было бы замечательным.

Спасибо, ребята, вы не представляете, насколько этот сайт помогает начинающему программисту, как я.

+0

(? yourRegEx) означает захваченную группу, которая может иметь имя «имя». Вот почему вы можете использовать extractor.Groups ["name"] – nickytonline

ответ

7

Ваша проблема заключается в жадности. Regex жадность, которая есть. Ваш. * В начале хватает все это «Это, надеюсь, поднимет 1Bob». попробуйте это регулярное выражение:

\d(?<name>[^\d]+)\d 
+0

Чад, я бы рекомендовал вам установить RegExWorkbench, http://code.msdn.microsoft.com/RegexWorkbench. Это старый проект, но удивительный, сделанный Эриком Гуннерсоном. Если у вас нет установленной платформы .NET 1.x, он предоставляет источник, чтобы вы могли скомпилировать его, используя установленную среду. – nickytonline

+0

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

+0

Вы должны помнить, что с регулярными выражениями,. и * может быть очень злым. Когда вы создаете свое регулярное выражение, вам действительно нужно знать, что вы хотите найти, и только это. Это требует времени, но как только вы сделаете это последовательно, вы получите твердые регулярные выражения. Я также рекомендую этот сайт, http://www.regular-expressions.info, и что вы читаете эту книгу, «Освоение регулярных выражений», http://regex.info. – nickytonline

3

Соответствует предшествующему элементу ноль или один раз. Это эквивалентно {0,1}. ? является жадным квантификатором, неживым эквивалентом которого является ??.

Взятый с here. Сайт включает в себя чит-лист для регулярных выражений, и, глядя на ваше выражение, я не могу понять, что может быть не так.

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

+0

Я мог ошибаться, но я не думаю, что это? является квантором в этом случае. Не квантификаторы обычно следуют за выражением? – Chad

+0

В выражении нет ничего плохого, он просто смотрит на второе значение, которое он захватывает, а не первый. – Rory

+0

@ Что? в этом контексте указывает начало именованной группы (точнее, имя с именем «имя»). В большинстве других мест он используется как квантификатор. – Rory

2

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

extractor.Groups["name"].Captures[0] 
+0

P.S. Каждый элемент Capture имеет свойство Value, которое возвращает фактическое строковое значение захвата, есть также некоторые другие полезные свойства, такие как индекс, в котором начинается захват в исходной строке и длительности захвата. Если у вас есть сомнения, нажмите F1. – Rory

+0

Хмммм ... полезная информация, но Captures [0] все еще поднимает «ошибку» Что-то не так со мной в регулярном выражении? – Chad

2

Брекетинг * персонажи вокруг вашего выражения вызывают у вас проблемы. Помните, что вам не нужно регулярное выражение, которое соответствует целой строке - вы хотите, чтобы она соответствовала только конкретному шаблону, когда он появляется. Работает следующий код:

Regex pattern = new Regex(@"\d(?<name>.*?)\d"); 
MatchCollection matches = pattern.Matches("This hopefully will pick up 1Bob9error1 as a name"); 
Console.WriteLine(matches[0].Groups["name"]);