Регулярные выражения C # - можно ли извлекать совпадения при сопоставлении?

Скажем, у меня есть строка, для которой мне нужно проверить правильный формат; например RR1234566-001 (2 буквы, 7 цифр, тире, 1 или более цифр). Я использую что-то вроде:

        Regex regex = new Regex(patternString);
        if (regex.IsMatch(stringToMatch))
        {
            return true;
        }
        else
        {
            return false;
        }

Это помогает мне сказать, следует ли stringToMatch шаблону, определенному patternString. Однако мне нужны (и я извлекаю их позже): 123456 и 001, то есть части stringToMatch.

Обратите внимание, что это НЕ вопрос о том, как создавать регулярные выражения. Я спрашиваю: «Есть ли способ сопоставлять и извлекать значения одновременно без использования функции разделения позже?»


person sarsnake    schedule 08.05.2009    source источник
comment
Обратите внимание, что вы можете просто вернуть: return regex.IsMatch(...) // code from the question или return match.Success // code from the accepted solution возвращается, если / иначе не нужны :)   -  person Frank Sebastià    schedule 27.01.2017


Ответы (3)


Для этого вы можете использовать группы регулярных выражений. Например, это регулярное выражение:

(\d\d\d)-(\d\d\d\d\d\d\d)

Сопоставим номер телефона с этим регулярным выражением:

var regex = new Regex(@"(\d\d\d)-(\d\d\d\d\d\d\d)");
var match = regex.Match("123-4567890");
if (match.Success)
    ....

Если он совпадает, вы найдете первые три цифры в:

match.Groups[1].Value

И вторые 7 цифр в:

match.Groups[2].Value

P.S. В C # вы можете использовать строку стиля @ "", чтобы не экранировать обратную косую черту. Например, @ "\ hi \" равно "\\ hi \\". Полезно для регулярных выражений и путей.

P.S.2. Первая группа хранится в группе [1], а не в группе [0], как вы ожидали. Это потому, что Group [0] содержит всю совпавшую строку.

person Andomar    schedule 08.05.2009
comment
+1 Очень основательно! Я бы добавил одну вещь: причина того, что вы начинаете с match.Groups [1], а не [0], заключается в том, что [0] содержит всю совпавшую строку. - person Neil Williams; 09.05.2009
comment
В именованных группах гораздо сложнее ошибиться, используйте вместо них new Regex(@"(?<areacode>\d\d\d)-(?<number>\d\d\d\d\d\d\d)");. - person TamaMcGlinn; 27.06.2019

Вместо этого используйте группировку и совпадения.

I.e.:

// NOTE: pseudocode.
Regex re = new Regex("(\\d+)-(\\d+)");
Match m = re.Match(stringToMatch))

if (m.Success) {
  String part1 = m.Groups[1].Value;
  String part2 = m.Groups[2].Value;
  return true;
} 
else {
  return false;
}

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

Regex re = new Regex("(?<Part1>\\d+)-(?<Part2>\\d+)");

и доступ как это

  String part1 = m.Groups["Part1"].Value;
  String part2 = m.Groups["Part2"].Value;
person cyberconte    schedule 08.05.2009

Вы можете использовать круглые скобки для захвата групп символов:

string test = "RR1234566-001";

// capture 2 letters, then 7 digits, then a hyphen, then 1 or more digits
string rx = @"^([A-Za-z]{2})(\d{7})(\-)(\d+)$";

Match m = Regex.Match(test, rx, RegexOptions.IgnoreCase);

if (m.Success)
{
    Console.WriteLine(m.Groups[1].Value);    // RR
    Console.WriteLine(m.Groups[2].Value);    // 1234566
    Console.WriteLine(m.Groups[3].Value);    // -
    Console.WriteLine(m.Groups[4].Value);    // 001
    return true;
}
else
{
    return false;
}
person LukeH    schedule 08.05.2009
comment
+1 для правильного регулярного выражения ... кстати, если вы используете IgnoreCase, вы можете использовать [a-z] вместо [A-Za-z]. - person Andomar; 09.05.2009