Вопрос
Я пытаюсь проанализировать строку, подобную следующей, используя регулярное выражение .NET:
H3Y5NC8E-TGA5B6SB-2NVAQ4E0
и верните следующее, используя Split:H3Y5NC8E TGA5B6SB 2NVAQ4E0
Я проверяю каждый символ на соответствие определенному набору символов (обратите внимание, что буквы «I», «O», «U» и «W» отсутствуют), поэтому использование string.Split не является вариантом.Количество символов в каждой группе может варьироваться, как и количество групп.Я использую следующее выражение:
([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8}-?){3}
Это будет соответствовать ровно 3 группам по 8 символов в каждой.Любое большее или меньшее значение приведет к провалу матча.Это работает, если оно правильно соответствует входным данным.Однако когда я использую метод Split для извлечения каждой группы символов, я получаю только окончательную группу.RegexBuddy жалуется, что я повторил саму группу захвата и что мне следует поместить группу захвата вокруг повторяющейся группы.Однако ни одна из моих попыток сделать это не привела к желаемому результату.Я пробовал такие выражения:
(([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8})-?){4}
Но это не работает.
Поскольку я генерирую регулярное выражение в коде, я мог бы просто расширить его по количеству групп, но я надеялся на более элегантное решение.
Обратите внимание, что набор символов не включает в себя весь алфавит.Это часть системы активации продукта.Таким образом, все символы, которые можно случайно интерпретировать как цифры или другие символы, удаляются.напримерБуквы «I», «O», «U» и «W» отсутствуют в наборе символов.
Дефисы не являются обязательными, поскольку пользователю не нужно их вводить, но они могут быть там, если пользователь выполнил копирование и вставку.
Решение 2
Я нашел ответ, который искал.Вот мой рабочий код:
static void Main(string[] args)
{
string pattern = @"^\s*((?<group>[ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8})-?){3}\s*$";
string input = "H3Y5NC8E-TGA5B6SB-2NVAQ4E0";
Regex re = new Regex(pattern);
Match m = re.Match(input);
if (m.Success)
foreach (Capture c in m.Groups["group"].Captures)
Console.WriteLine(c.Value);
}
Другие советы
Кстати, вы можете заменить класс символов [ABCDEFGHJKLMNPQRSTVXYZ0123456789] на более читаемый вычитаемый класс символов.
[[A-Z\d]-[IOUW]]
Если вы просто хотите сопоставить 3 такие группы, почему бы вам не использовать этот шаблон 3 раза в своем регулярном выражении и просто использовать захваченные 1, 2, 3 подгруппы для формирования новой строки?
([[A-Z\d]-[IOUW]]){8}-([[A-Z\d]-[IOUW]]){8}-([[A-Z\d]-[IOUW]]){8}
В PHP я бы вернулся (не знаю .NET)
return "$1 $2 $3";
Изучив ваш вопрос и полученные ответы, я пришел к следующему:
RegexOptions options = RegexOptions.None;
Regex regex = new Regex(@"([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8})", options);
string input = @"H3Y5NC8E-TGA5B6SB-2NVAQ4E0";
MatchCollection matches = regex.Matches(input);
for (int i = 0; i != matches.Count; ++i)
{
string match = matches[i].Value;
}
Поскольку «-» не является обязательным, его не нужно включать.Я не уверен, для чего вы использовали {4} в конце?Это позволит найти совпадения в зависимости от того, что вы хотите, а затем, используя MatchCollection, вы сможете получить доступ к каждому совпадению, чтобы перестроить строку.
Зачем использовать Regex?Если группы всегда разделяются знаком -, разве вы не можете использовать Split()?
Извините, если это не то, что вы хотели, но в вашей строке всегда есть дефис, разделяющий группы, тогда вместо использования регулярного выражения не могли бы вы использовать метод String.Split()?
Dim stringArray As Array = someString.Split("-")
Каковы определяющие характеристики допустимого блока?Нам нужно это знать, чтобы действительно быть полезными.
Мое общее предложение: сначала проверьте кодировку, а затем разделите и проанализируйте ее отдельным методом в зависимости от того, что вы ожидаете.Если это находится на веб-сайте/приложении, вы можете использовать проверку ASP Regex во внешнем интерфейсе, а затем разбить ее на серверной части.
Если вы просто проверяете значение группы с помощью group(i).value, вы получите только последнее.Однако, если вы хотите перечислить все случаи захвата группы, используйте group(2).captures(i).value, как показано ниже.
system.text.RegularExpressions.Regex.Match("H3Y5NC8E-TGA5B6SB-2NVAQ4E0","(([ABCDEFGHJKLMNPQRSTVXYZ0123456789]+)-?)*").Groups(2).Captures(i).Value
Майк,
Вы можете использовать набор символов по вашему выбору внутри группы символов.Все, что вам нужно, это добавить модификатор «+», чтобы захватить все группы.Смотрите мой предыдущий ответ, просто измените [A-Z0-9] на то, что вам нужно (т.е.[ABCDEFGHJKLMNPQRSTVXYZ0123456789])
Вы можете использовать этот шаблон:
Regex.Split("H3Y5NC8E-TGA5B6SB-2NVAQ4E0", "([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8}+)-?")
Но вам нужно будет отфильтровать пустые строки из результирующего массива.Цитата из MSDN:
Если несколько совпадений соседствуют друг с другом, в массив вставляется пустая строка.