Как сопоставить только определенные символы в заданной строке с регулярным выражением?

Мне нужно конкретное значение, значение должно быть только цифрами и:

  • Длина должна быть 11.

  • Первая цифра должна быть 0.

  • Вторая цифра должна быть 1.

  • Третья цифра должна быть 0, 1, 2, 5.

  • Затем сопоставьте любую цифру с четвертой цифры до конца.

  • Если третья цифра равна 1, то последние две цифры (10-я, 11-я) должны быть одинаковыми.

  • Если третья цифра 2, 8-я, 9-я цифры должны быть одинаковыми.

Входная строка и ожидаемый результат.

01012345678          -----> allowed.
0101234a5678         -----> not allowed., letter exists.
01112345688          -----> allowed, 10th, 11st are the same
01112345677          -----> allowed, 10th, 11st are the same
01112345666          -----> allowed, 10th, 11st are the same
01112345689          -----> not allowed..10th, 11st different
01112345-678         -----> not allowed..hyphen exists.
01298765532          -----> allowed..8th, 9th are the same.
01298765732          -----> not allowed, 8th, 9th different.
01298765mm432        -----> not allowed, letter exists.
01500011122          -----> allowed..
020132156456136      -----> not allowed..more than 11 digit.
01530126453333       -----> not allowed..more than 11 digit.
00123456789          -----> not allowed.. second digit not 1.

Это моя попытка regex101, ^01[0125][0-9]{8}$ https://regex101.com/r/cIcD0R/1, но она игнорирует определенные случаи и работает для конкретных случаев.

Что такое двойные вопросительные знаки (??) в JavaScript?
Что такое двойные вопросительные знаки (??) в JavaScript?
Как безопасно обрабатывать неопределенные и нулевые значения в коде с помощью Nullish Coalescing
Асинхронная передача данных с помощью sendBeacon в JavaScript
Асинхронная передача данных с помощью sendBeacon в JavaScript
В современных веб-приложениях отправка данных из JavaScript на стороне клиента на сервер является распространенной задачей. Одним из популярных...
Принципы ООП в JavaScript
Принципы ООП в JavaScript
Парадигма объектно-ориентированного программирования имеет 4 основных принципа,
Laravel с Turbo JS
Laravel с Turbo JS
Turbo - это библиотека JavaScript для упрощения создания быстрых и высокоинтерактивных веб-приложений. Она работает с помощью техники под названием...
Слишком много useState? Давайте useReducer!
Слишком много useState? Давайте useReducer!
Современный фронтенд похож на старую добрую веб-разработку, но с одной загвоздкой: страница в браузере так же сложна, как и бэкенд.
Типы данных JavaScript
Типы данных JavaScript
В JavaScript существует несколько типов данных, включая примитивные типы данных и ссылочные типы данных. Вот краткое объяснение различных типов данных...
21
0
1 295
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

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

^01(?:[05]\d{8}|1\d{6}(\d)\1|2\d{4}(\d)\2\d\d)$

Объяснение

  • ^ Начало строки
  • 01 Совпадение буквально
  • (?: Группа без захвата для альтернатив
    • [05]\d{8} Сопоставьте либо 0, либо 5 и 8 цифр.
    • | Или
    • 1\d{6}(\d)\1 Сопоставьте 1, затем 6 цифр, зафиксируйте одну цифру в группе 1, за которой следует обратная ссылка для соответствия той же цифре
    • | Или
    • 2\d{4}(\d)\2\d\d Сопоставьте 2, затем 4 цифры, захватите одну цифру в группе 2, за которой следует обратная ссылка, чтобы сопоставить ту же цифру и сопоставить последние 2 цифры
  • ) Закройте группу без захвата
  • $ Конец строки

Посмотрите демоверсию regex101

const regex = /^01(?:[05]\d{8}|1\d{6}(\d)\1|2\d{4}(\d)\2\d\d)$/;
[
  "01012345678",
  "0101234a5678",
  "01112345688",
  "01112345677",
  "01112345666",
  "01112345689",
  "01112345-678",
  "01298765532",
  "01298765732",
  "01298765mm432",
  "01500011122",
  "020132156456136",
  "01530126453333",
  "00123456789"
].forEach(s => console.info(`${s} => ${regex.test(s)}`))

С вашими показанными образцами попробуйте выполнить регулярное выражение. Вот Онлайн-демонстрация для используемого регулярного выражения.

^01(?:(?:[05][0-9]{8})|(?:1[0-9]{6}([0-9])\1)|(?:2[0-9]{4}([0-9])\2[0-9]{2}))$

Вот код JS для приведенного выше регулярного выражения, в котором используется цикл foreach вместе с использованием функции test.

const regex = /^01(?:(?:[05][0-9]{8})|(?:1[0-9]{6}([0-9])\1)|(?:2[0-9]{4}([0-9])\2[0-9]{2}))$/;
[
  "01012345678",
  "0101234a5678",
  "01112345688",
  "01112345677",
  "01112345666",
  "01112345689",
  "01112345-678",
  "01298765532",
  "01298765732",
  "01298765mm432",
  "01500011122",
  "020132156456136",
  "01530126453333",
  "00123456789"  
].forEach(element => 
  console.info(`${element} ----> ${regex.test(element)}`)
);

Объяснение: добавлено подробное объяснение используемого регулярного выражения.

^01                              ##Matching 01 from starting of the value.
(?:                              ##Starting outer non-capturing group from here.
  (?:                            ##In a non-capturing group
    [05][0-9]{8}                 ##Matching 0 OR 5 followed by any other 8 digits.
  )
  |                              ##Putting OR condition here.
  (?:                            ##In a non-capturing group
    1[0-9]{6}([0-9])\1           ##Matching 1 followed by 6 digits followed by single digit(in a capturing group) and making sure next digit is matching previous.
  )
  |                              ##Puting OR condition here.
  (?:                            ##In a non-capturing group matching, 2 followed by 4 digits followed by 1 digit in capturing group followed by it followed by 2 any other digits.
    2[0-9]{4}([0-9])\2[0-9]{2}
  )
)$                               ##Closing outer non-capturing grouo here at the last of the value.

Если вы ищете регулярное выражение исключительно для фильтрации определенных чисел без сообщений об ошибках, этот ответ, вероятно, не для вас.

Для целей проверки регулярное выражение может быть не лучшим способом. Если бы вы использовали одно гигантское регулярное выражение, вы бы показали одно универсальное сообщение об ошибке. Это может ввести пользователя в замешательство, поскольку он частично соответствует некоторым критериям.

Вместо этого разделите критерии, чтобы вы могли показывать пользователю релевантные сообщения об ошибках.

function isValid(input, criteria) {
  const errors = [];
  
  for (const [isValid, error] of criteria) {
    if (!isValid(input)) errors.push(error);
  }
    
  return [!errors.length, errors];
}

const criteria = [
  [input => input.length === 11,
    "must have a length of 11"],
  [input => input.match(/^\d*$/),
    "must only contain digits (0-9)"],
  [input => input[0] === "0",
    "must have 0 as 1st digit"],
  [input => input[1] === "1",
    "must have 1 as 2nd digit"],
  [input => ["0","1","2","5"].includes(input[2]),
    "must have 0, 1, 2 or 5 as 3rd digit"],
  [input => input[2] !== "1" || input[9] === input[10],
    "the 10th and 11th digit must be the same if the 3rd digit is 1"],
  [input => input[2] !== "2" || input[7] === input[8],
    "the 8th and 9th digit must be the same if the 3rd digit is 2"],
];

document.forms["validate-number"].addEventListener("submit", function (event) {
  event.preventDefault();
  
  const form = event.target;
  const inputs = form.elements.inputs.value.split("\n");
  
  inputs.forEach(input => console.info(input, ...isValid(input, criteria)));
});
<form id = "validate-number">
<textarea name = "inputs" rows = "14" cols = "15">01012345678
0101234a5678
01112345688
01112345677
01112345666
01112345689
01112345-678
01298765532
01298765732
01298765mm432
01500011122
020132156456136
01530126453333
00123456789</textarea>
<br />
<button>validate</button>
</form>

Другие вопросы по теме

Установите условие внутри лямбда-функции в зависимости от того, является ли значение, захваченное с помощью регулярного выражения, None или ""
Переименование нескольких файлов в каталоге с использованием определенной строки в каждом файле
Извлечь первый символ всех слов, кроме первого
Разбор дат в другом формате из текста
Мне нужно регулярное выражение, чтобы аннулировать все одинаковые цифры в номере телефона
Использование регулярных выражений для извлечения определенной информации через PyPDF2
Установите регулярное выражение с множественным выбором, чтобы попытки сопоставления всегда выполнялись слева направо, независимо от того, пытается ли другое предыдущее регулярное выражение захватить больше символов?
Сравнение значений из двух списков с помощью регулярных выражений в Kotlin
Извлечь слово из строки в определенной позиции в сценарии bash
Соедините Lookbehind и Lookahead