Регулярное выражение, где часть строки должна быть числом от 0 до 100 - PullRequest
6 голосов
/ 15 декабря 2009

Мне нужно проверить серийные номера. Для этого мы используем регулярные выражения в C #, а для определенного продукта частью серийного номера являются «секунды с полуночи». В дне 86400 секунд, но как я могу проверить его как 5-значное число в этой строке?:

654984051-86400-231324

Я не могу использовать эту концепцию:

[0-8][0-6][0-4][0-0][0-0]

Потому что тогда 86399 не будет действительным. Как я могу преодолеть это? Я хочу что-то вроде:

[00000-86400]

UPDATE
Я хочу прояснить, что я знаю - и согласен с - «не используйте регулярные выражения, когда есть более простой способ» школа мысли. Ответ Джейсона - это именно то, что я хотел бы сделать, однако эта проверка серийных номеров предназначена для всех серийных номеров, которые проходят через нашу систему - в настоящее время для этих конкретных пользовательских кодов проверки нет. В этом случае У меня есть веская причина для поиска решения для регулярных выражений.

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

Ответы [ 7 ]

10 голосов
/ 15 декабря 2009

Не используете регулярные выражения? Если вы изо всех сил пытаетесь придумать регулярное выражение для анализа этого, которое говорит, что, возможно, это слишком сложно, и вы должны найти что-то более простое. Я не вижу абсолютно никакой пользы от использования регулярных выражений здесь, когда простой

int value;
if(!Int32.TryParse(s, out value)) {
    throw new ArgumentException();
}
if(value < 0 || value > 86400) {
    throw new ArgumentOutOfRangeException();
}

будет работать просто отлично. Это так просто и легко обслуживается.

7 голосов
/ 15 декабря 2009

Вы не хотите пытаться использовать регулярные выражения для этого, вы получите что-то непонятное, громоздкое и сложное для изменения (кто-то, вероятно, предложит такое :). Что вы хотите сделать, это сопоставить строку с помощью регулярного выражения, чтобы убедиться, что она содержит цифры в желаемом формате , затем вынуть соответствующую группу и проверить диапазон, используя арифметическое сравнение. Например, в псевдокоде:

match regex /(\d+)-(\d+)-(\d+)/
serial = capture group 2
if serial >= 0 and serial <= 86400 then
    // serial is valid
end if
6 голосов
/ 15 декабря 2009

Создание регулярного выражения для соответствия произвольному числовому диапазону http://utilitymill.com/utility/Regex_For_Range

дает следующее выражение регулярного выражения:

\b0*([0-9]{1,4}|[1-7][0-9]{4}|8[0-5][0-9]{3}|86[0-3][0-9]{2}|86400)\b

Описание выхода:

First, break into equal length ranges:
  0 - 9
  10 - 99
  100 - 999
  1000 - 9999
  10000 - 86400

Second, break into ranges that yield simple regexes:
  0 - 9
  10 - 99
  100 - 999
  1000 - 9999
  10000 - 79999
  80000 - 85999
  86000 - 86399
  86400 - 86400

Turn each range into a regex:
  [0-9]
  [1-9][0-9]
  [1-9][0-9]{2}
  [1-9][0-9]{3}
  [1-7][0-9]{4}
  8[0-5][0-9]{3}
  86[0-3][0-9]{2}
  86400

Collapse adjacent powers of 10:
  [0-9]{1,4}
  [1-7][0-9]{4}
  8[0-5][0-9]{3}
  86[0-3][0-9]{2}
  86400

Combining the regexes above yields:
  0*([0-9]{1,4}|[1-7][0-9]{4}|8[0-5][0-9]{3}|86[0-3][0-9]{2}|86400)

Проверено здесь: http://osteele.com/tools/rework/

6 голосов
/ 15 декабря 2009

Со стандартным предупреждением «проблема не в регулярном выражении»

[0-7]\d{4}|8[0-5]\d{3}|86[0-3]\d{2}|86400 
0 голосов
/ 15 декабря 2009

Я бы использовал регулярное выражение в сочетании с некоторым кодом .NET для достижения этой цели. Чистое решение регулярных выражений не будет легким или эффективным для обработки большого числа диапазонов.

Но это будет:

Regex myRegex = new Regex(@"\d{9}-(\d{5})-\d{6}");
String value = myRegex.Replace(@"654984051-86400-231324", "$1");

В этом случае будет получено значение 86400. И тогда вы просто проверите, будет ли захваченное число между 0 и 86400 согласно ответу Джейсона.

0 голосов
/ 15 декабря 2009

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

([0-7][0-9]{4}) | (8[0-5][0-9]{3}) | (86[0-3][0-9]{2}) | (86400)
0 голосов
/ 15 декабря 2009

Я не верю, что это возможно в регулярных выражениях, поскольку это нельзя проверять как часть обычного языка. Другими словами, автомат конечных состояний не может распознать эту строку, поэтому регулярное выражение также не может.

Редактировать: это может быть распознано регулярным выражением, но не элегантным способом. Для этого потребуется цепочка монстров или (например: 00000|00001|00002 или 0{1,5}|0{1,4}1|0{1,4}2). Для меня необходимость перечислять такой большой набор возможностей дает понять, что, хотя это технически возможно, оно неосуществимо и не поддается управлению.

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