В регулярном выражении C # почему первоначальное совпадение отображается в группах? - PullRequest
12 голосов
/ 12 февраля 2010

Так что, если я напишу регулярное выражение, это совпадения, я могу получить совпадение или получить доступ к его группам. Это кажется противоречащим интуиции, так как группы определены в выражении в скобках "(" и ")". Кажется, это не только неправильно, но и излишне. Кто-нибудь знает почему?

Regex quickCheck = new Regex(@"(\D+)\d+");
string source = "abc123";

m.Value        //Equals source
m.Groups.Count //Equals 2
m.Groups[0])   //Equals source
m.Groups[1])   //Equals "abc"

Ответы [ 8 ]

4 голосов
/ 12 февраля 2010

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

Regex Match само по себе Group, что, в свою очередь, Capture.

Но Match.Value (или Capture.Value в том виде, в каком он есть на самом деле) действителен, только если в строке присутствует одно совпадение - если вы сопоставляете несколько экземпляров шаблона, то по определению он не может вернуть все , Фактически - свойство Value в Match соответствует удобству, когда есть только совпадение.

Но чтобы выяснить, где такое поведение передачи всего совпадения в Groups[0] имеет смысл - рассмотрим этот (надуманный) пример унификатора наивного кода:

[TestMethod]
public void UnMinifyExample()
{
  string toUnMinify = "{int somevalue = 0; /*init the value*/} /* end */";
  string result = Regex.Replace(toUnMinify, @"(;|})\s*(/\*[^*]*?\*/)?\s*", "$0\n");
  Assert.AreEqual("{int somevalue = 0; /*init the value*/\n} /* end */\n", result);
}

Соответствие регулярному выражению сохранит / * * / комментарии в конце оператора, а затем добавит новую строку - но работает для любого из них; или} окончания строки.

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

Если бы Groups[0], сгенерированный совпадениями для этого регулярного выражения, не был полным захватом - тогда замена одним вызовом была бы невозможна - и ваш вопрос, вероятно, задавал бы вопрос, почему не полностью Матч вставляется в Groups[0], а не наоборот!

4 голосов
/ 12 февраля 2010

Документация для Match гласит, что первая группа - это всегда полное совпадение, поэтому это не детали реализации.

2 голосов
/ 12 февраля 2010

Это историческое все. В Perl 5 содержимое групп захвата хранится в специальных переменных $1, $2 и т. Д., Но C #, Java и другие вместо этого хранят их в массиве (или в структуре, похожей на массив). Чтобы сохранить совместимость с соглашением об именах Perl (которое было скопировано несколькими другими языками), первая группа сохраняется в элементе номер один, вторая - в элементе два и т. Д. Это оставляет элемент нулевым свободным, поэтому почему бы не сохранить полное совпадение ?

К вашему сведению, Perl 6 принял новое соглашение, в котором первая группа захвата нумеруется с нуля вместо единицы. Я уверен, что не было сделано просто чтобы разозлить нас. ;)

1 голос
/ 12 февраля 2010

Скорее всего, вы можете использовать "$ 0" для представления соответствия в выражении подстановки и "$ 1" для первого совпадения группы и т. Д.

0 голосов
/ 12 февраля 2010

Обратные ссылки основаны на единицах, , например, , \1 или $1 - это первое подвыражение в скобках и т. Д. Как изложено, один отображается на другой без каких-либо мыслей.

Также обратите внимание: m.Groups["0"] дает вам всю подобранную подстроку, поэтому обязательно пропустите "0", если вы перебираете regex.GetGroupNames().

0 голосов
/ 12 февраля 2010

Может быть избыточным, но обладает некоторыми приятными свойствами.

Например, это означает, что группы захвата работают так же, как и другие движки регулярных выражений - первая группа захвата соответствует «1» и т. Д.

0 голосов
/ 12 февраля 2010

Не знаю почему, но если вы используете именованные группы, вы можете установить параметр RegExOptions.ExplicitCapture , и он не должен включать источник в качестве первой группы.

0 голосов
/ 12 февраля 2010

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

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