Regex положительный взгляд на "содержит 10-14 цифр" не работает правильно - PullRequest
0 голосов
/ 27 апреля 2020

У меня есть регулярное выражение, предназначенное для проверки того, что строка телефонного номера либо пуста, либо содержит 10-14 цифр в любом формате. Это работает для того, чтобы требовать минимум 10, но продолжает совпадать после 14 цифр. Раньше я редко пользовался прогнозом и не вижу проблемы. Вот это с предполагаемой интерпретацией в комментариях:

///  ^                      - Beginning of string
/// (?=                     - Look ahead from current position
///      (?:\D*\d){10,14}       - Match 0 or more non-digits followed by a digit, 10-14 times
///      \D*$                   - Ending with 0 or more non-digits
/// .*                      - Allow any string
/// $                       - End of string
^(?=(?:\D*\d){10,14}\D*|\s*$).*$

Это используется на asp. net MVC 5 сайте с System.ComponentModel.DataAnnotations.RegularExpressionAttribute, поэтому он используется на стороне сервера с . NET Регулярные выражения и клиентская часть в javascript с jquery validate. Как я могу заставить это остановить соответствие, если строка содержит больше чем 14 цифр?

1 Ответ

1 голос
/ 27 апреля 2020

Проблема с регулярным выражением

^(?=(?:\D*\d){10,14}\D*|\s*$).*$

заключается в том, что между \D и | отсутствует привязка конца строки. Рассмотрим, например, строку

12345678901234567890

, которая содержит 20 цифр. Ожидание будет удовлетворено, потому что (?:\D*\d){10,14} будет соответствовать

12345678901234

, а затем \D* будет соответствовать нолю без цифр. Напротив, регулярное выражение

^(?=(?:\D*\d){10,14}\D*$|\s*$).*$

не удастся (как и должно быть).

Однако нет необходимости в заглядывании вперед. Можно упростить предыдущее выражение до

^(?:(?:\D*\d){10,14}\D*)?$

Демонстрация

Необязательная внешняя группа без захвата позволяет регулярному выражению при необходимости сопоставлять пустые строки.

Может быть проблема с этим последним регулярным выражением, как показано на ссылке. Рассмотрим строку

\nabc12\nab12c3456d789efg

Первое совпадение (?:\D*\d) будет \nabc1 (так как \D соответствует переводу строк), а второе совпадение будет 2, третье, \nab1 и и так, в общей сложности 11 совпадений, удовлетворяющих требованию, что должно быть 10-14 цифр. Это, несомненно, не предназначено. Решение состоит в том, чтобы изменить регулярное выражение на

^(?:(?:[^\d\n]*\d){10,14}[^\d\n]*)?$

[^\d\n] соответствует любому символу, кроме ди git и новой строки.

Демо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...