Вопрос

Я пытаюсь проанализировать строку, подобную следующей, используя регулярное выражение .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:

Если несколько совпадений соседствуют друг с другом, в массив вставляется пустая строка.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top