Regex для разделения различных кодов из длинной строки кодов без разделов - PullRequest
1 голос
/ 28 июня 2019

У меня есть (по сути) файл из 600 000 кодов.

Они выглядят так:

HJ43EKU2

Когда они сохранены / загружены, они выглядят так:

BJX4700QHJ43EKU2KU89EJKM

Каждый код состоит из 8 цифр.

Они являются буквенно-цифровыми (a-Z, 0-9) без акцентов и символов.

Так что это работает (для разделения блоков кода):

[a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9]

Но есть проблема, поскольку определенные форматы кодов не являются действительными кодами, подобными этому:

MF93276H

Седьмая цифра не может быть числовой.

Это было бы не так уж и плохо, если не считать исключения, если 2-я цифра кода равна N (или позже в алфавите), тогда это делает код снова действительным.

Как мне реализовать некоторую логику в REGEX, чтобы она учитывала «исключение» из правила повторной проверки кода?

Ответы [ 3 ]

3 голосов
/ 28 июня 2019

В C # вы можете использовать известную технику с использованием группы захвата и последующей ее оценки:

var rx = "[a-zA-Z0-9]N[a-zA-Z0-9]{4}[0-9][a-zA-Z0-9]|([a-zA-Z0-9]{6}[0-9][a-zA-Z0-9])|[a-zA-Z0-9]{6}[a-zA-Z][a-zA-Z0-9]";
var results = Regex.Matches("BJX4700QHJ43EKU2KU89EJKM", rx)
            .Cast<Match>()
            .Where(m => !m.Groups[1].Success)
            .Select(z => z.Value);
foreach (var s in results)
    Console.WriteLine(s);

См. Демонстрационную версию C #

Regexдетали

  • [a-zA-Z0-9]N[a-zA-Z0-9]{4}[0-9][a-zA-Z0-9] - допустимый кодовый образец со вторым символом, равным N
  • | - или
  • ([a-zA-Z0-9]{6}[0-9][a-zA-Z0-9]) -Группа 1 (если найдено, отменить ее): неверный кодовый шаблон
  • | - или
  • [a-zA-Z0-9]{6}[a-zA-Z][a-zA-Z0-9] - действительный кодовый шаблон.

ПРИМЕЧАНИЕ : Если N (или позже в алфавите) означает, что если второй символ равен O, P .. Z, вам необходимо заменить N в первомальтернатива [N-Z].

Сведения о коде

  • .Where(m => !m.Groups[1].Success) - если группа 1 не совпадает, совпадение является допустимым кодом, поэтому возьмите этиonly
  • .Select(z => z.Value) - сохраняет весь текст значения объекта соответствия только в результате.
1 голос
/ 28 июня 2019

Я бы использовал альтернативную конструкцию:

var x = @"HJ43EKU2";
var match =
    Regex.Match(x, @"(?i)[a-z0-9](?([n-z])[a-z0-9]{7}|[a-z0-9]{5}[a-z][a-z0-9])");
var code = match.Value;

(?i) Сделать поиск без учета регистра

(?(n-z)) Утверждение нулевой ширины, которое проверяет, является ли 2-й символравно N или «больше»

[a-z0-9]{7} Если 2-й символ равен N или более, то 7-й символ должен быть числовым

[a-z0-9]{5}[a-z][a-z0-9] Если 2-й символ не N или более, запрещает 7-й символ числовой

1 голос
/ 28 июня 2019

Я не могу рекомендовать против это достаточно сильно, но .NET фактически поддерживает условные группы, поэтому вы могли бы сделать:

var pattern = "[a-zA-Z0-9](?:(?<n>N)|[a-zA-Z0-9-[nN]])[a-zA-Z0-9]{4}(?(n)[a-zA-Z0-9]|[a-zA-Z])[a-zA-Z0-9]";
Regex.IsMatch("MF93276H") // false
Regex.IsMatch("MN93276H") // true
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...