Разрешающая цифра, точка, запятая - PullRequest
17 голосов
/ 17 мая 2019

Я хотел бы знать, что регулярное выражение для c # выполняет следующий шаблон:

  • разрешают только цифры, запятую и цифру
  • должны начинаться и заканчиваться цифрой
  • диапазон цифр от 0 до 999
  • цифр (например, 1,2,3) или диапазон (например, 1-3, 2-5) разделены символом ',' *
  • между двумя',' должен быть цифрой или диапазоном
  • '-' должен начинаться и заканчиваться цифрой
  • Разрешить только 0-1 пробел после ','

Пример:

1-100,134,200 --> PASS. Maximum range of numbers 0-999
1,18,100      --> PASS
1, 18, 100    --> PASS. Allow 0-1 white space after ',' 
1,  18,100    --> FAIL. Due to more than 1 white space after ','
1-,18,100     --> FAIL. Due to no digit after '-'
-2,18,100     --> FAIL. Due to no digit before '-'
1,,18,100     --> FAIL. Due to no digit between ','
1, ,18,100    --> FAIL. Due to no digit between ','
,2,18,100     --> FAIL. Due to no digit before ','
1,18,100,     --> FAIL. Due to no digit after ','

Я пытался использовать следующий код, но он всегда возвращает верный результат:

string pattern = @"[0-9]+(?:-[0-9]+)?(,[0-9]+(?:-[0-9]+)?)*";
string test = @"1-5,13,238,-a";
bool result = Regex.IsMatch(test, pattern);

Ответы [ 5 ]

7 голосов
/ 17 мая 2019

Вы можете использовать это регулярное выражение,

^(?:[1-9]\d\d|[1-9]?\d)(?:-(?:[1-9]\d\d|[1-9]?\d))?(?:,\s?(?:[1-9]\d\d|[1-9]?\d)(?:-(?:[1-9]\d\d|[1-9]?\d))?)*$

Пояснение:

  • ^ - начало строки
  • (?:[1-9]\d\d|[1-9]?\d) - представляет число от 0 до 999 и не допускает чисел с начальными нулями, таких как 005
  • (?:-(?:[1-9]\d\d|[1-9]?\d))? - Опционально также допускается число, разделенное дефисом -, поэтому вместе с первой цифрой регулярного выражения он поддерживает такие числа, как 22 и 22-33 и т. Д.
  • (?:,\s?(?:[1-9]\d\d|[1-9]?\d)(?:-(?:[1-9]\d\d|[1-9]?\d))?)* - Эта часть просто поддерживает запятую, разделенную необязательно, за которой следует пробел, и все это ноль или более раз
  • $ - конец строки

Я мог бы использовать \d{1,3} для представления числа от 0 до 999, но это позволило бы таким числам, как 004, которые, по-видимому, не позволяют просматривать данные вашего образца. Но если действительно допустимо использовать числа типа 004 или 04, тогда вы можете заменить [1-9]\d\d|[1-9]?\d на \d{1,3} в моем регулярном выражении, чтобы сделать его простым.

Regex Demo

6 голосов
/ 17 мая 2019

Вы можете попробовать

   ^[0-9]{1,3}(?:\-[0-9]{1,3})?(?:,\s?[0-9]{1,3}(?:\-[0-9]{1,3})?)*$

шаблон, где

   ^                             String start
   0*[0-9]{1,3}                  1 to 3 digits
   (?:\-[0-9]{1,3})?             Possible minus (-) followed 1 to 3 digits (e.g. -456)
   ?:,\s?                        Comma and at most one whitespace  
   [0-9]{1,3}(?:\-[0-9]{1,3})?)* 1 to 3 digits or range repeated zero or more times
   $                             End of string        

Демо-версия:

  string pattern = 
    @"^[0-9]{1,3}(?:\-[0-9]{1,3})?(?:,\s?[0-9]{1,3}(?:\-[0-9]{1,3})?)*$";

  string[] tests = new string[] {
    "123",
    "1234",
    "123-456",
    "123,456",
    "1-100,134,200",
    "1,18,100",
    "1, 18, 100",
    "1,  18,100",
    "1-,18,100",
    "-2,18,100",
    "1,,18,100",
    "1, ,18,100",
    ",2,18,100",
    "1,18,100,",
  };

  string[] results = tests
    .Select(test => $"{test,-20} --> {(Regex.IsMatch(test, pattern) ? "PASS" : "FAIL")}")
    .ToArray();

  string report = string.Join(Environment.NewLine, results);

  Console.Write(report);

Результат:

123                  --> PASS
1234                 --> FAIL 
123-456              --> PASS
123,456              --> PASS
1-100,134,200        --> PASS
1,18,100             --> PASS
1, 18, 100           --> PASS
1,  18,100           --> FAIL
1-,18,100            --> FAIL
-2,18,100            --> FAIL
1,,18,100            --> FAIL
1, ,18,100           --> FAIL
,2,18,100            --> FAIL
1,18,100,            --> FAIL

Редактировать:

  • Если вы хотите разрешить произвольное количество ведущих нулей (например, 000123, что на самом деле 123), измените каждый фрагмент [0-9]{1,3} на 0*[0-9]{1,3}
  • Если вы хотите запретить начальные нули (012 должен произойти сбой, когда 12 или 0 должен пройти), измените каждый фрагмент [0-9]{1,3} на (?:0|[1-9][0-9]{0,2})
3 голосов
/ 17 мая 2019

Попробуйте следующий шаблон: ^(?:\d{1,3}-\d{1,3}|\d{1,3})(?:, ?(?:\d{1,3}-\d{1,3}|\d{1,3}))*$

Объяснение:

^ - совпадение начала строки

(?:...) - группа без захвата

\d{1,3} - совпадение от 1 до 3 цифр

- - сопоставление буквально тире

| - чередование, совпадение с тем, что справа (\d{1,3}) или чтослева (\d{1,3}-\d{1,3})

, ? - совпадение ,, за которым следует ноль или один пробел

* - совпадение (?:, ?(?:\d{1,3}-\d{1,3}|\d{1,3})) ноль или более раз

$ - совпадение конца строки

Демо

1 голос
/ 17 мая 2019

Кажется, здесь много необычно сложных ответов, поэтому вот мои 2 цента:

^([1-9]\d{0,2}|0)((\-|, ?)([1-9]\d{0,2}|0))*$

Я считаю этот ответ "менее сложным" не потому, что он короче (здесь он не самый короткий), но поскольку он не использует «сложное» поведение регулярных выражений.
Он использует только общие группы соответствия (), общие квантификаторы (*, {,} и ?) и общие символы соответствия, такие как \dи [1-9]

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

Объяснение:

^([1-9]\d{0,2}|0)((\-|, ?)([1-9]\d{0,2}|0))*$
^                                               Start of string
 (                                              Start of capture group:
  [1-9]\d{0,2}                                    A non-zero digit followed by 0 to 2 digits.
                                                    Matches any 1-999 number without leading zeroes
              |                                   OR
               0                                  Just a zero
                )                               End of capture group
                 (                             Start of capture group:
                  (                              Start of capture group:
                   \-                              Dash
                     |                             OR
                      , ?                          Comma Followed by 1 or 0 spaces
                         )                       End of capture group
                          ([1-9]\d{0,2}|0)       Same 0-999 capture group as earlier
                                          )     End of capture group
                                           *    Previous capture group matched 0 or more times
                                            $   End of string

Короче говоря, если вам нужно чуть менее техническое описание:

Number - это число от 0-999
(обозначается с помощью регулярного выражения: ([1-9]\d{0,2}|0))

Separator - это запятая плюс 0 или 1 пробел или тире
(обозначается регулярным выражением: (\-|, ?))

Group - это Разделитель , за которым сразу следует Число
(Представлено с помощью регулярного выражения: ((\-|, ?)([1-9]\d{0,2}|0)))

Это регулярное выражение соответствует:
A Число , за которым следует ноль или более Группы

Обновление

@ bobblebubble в комментариях указано, что это позволит, например 1-2-3, что не может быть разрешено, учитывая, что - предназначен для указания диапазона.

Вот модификация, которая исправляет это:

^(([1-9]\d{0,2}|0)(-([1-9]\d{0,2}|0))?)(, ?(([1-9]\d{0,2}|0)(-([1-9]\d{0,2}|0))?))*$

Это намного дольше, чем оригинал,поэтому в C # я бы разделил его следующим образом:

// This pattern will match a single 0-999 number, or a range
string numPatt = "(([1-9]\d{0,2}|0)(-([1-9]\d{0,2}|0))?)";
// This pattern will match a csv of numPatts
string pattern = $"^{numPatt}(, ?{numPatt})*$";

Затем используйте pattern по желанию.

1 голос
/ 17 мая 2019

Вот моя попытка с использованием \b a границы слова , возможно, она достаточно точна для ваших нужд.

^(?:\d{1,3}(?:-\d{1,3})?(?:, ?)?\b)+$

Поиграйте с ней в в этой демонстрации на регулярном выражении 101 (пояснение справа).

Если вам нужна проверка 0-999 без начальных нулей, замените \d{1,3} на (?:[1-9]\d\d?|\d)

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