2012-02-24 4 views
5

Так что это очевидный случай: «Вы делаете это неправильно». На самом деле я намереваюсь это делать, но разговор на работе подстегнул этот вопрос:Использование регулярных выражений для сравнения чисел

Можете ли вы создать регулярное выражение, чтобы определить, меньше ли целое число, чем любое значение.

Для некоторых значений это очень просто. Для целых чисел менее 1000, \ d {1,3} должен делать трюк. Для целых чисел < 500 это немного сложнее, но не так уж плохо, поскольку вы можете использовать [0-4] {0,1} \ d {1,2}.

Как только вы попадаете на произвольные значения, это становится очень сложным. Например, все числа меньше 255 будут выглядеть как \ d {1,2} | [0-1] \ d {2} | [2] [0-4] \ d | [2] [5] [0-4].

Есть ли одно регулярное выражение, которое работает здесь? Или вам нужно программно генерировать регулярное выражение?

(И опять же, позвольте мне сказать, что я не имею никакого намерения фактически это делать. Очевидно, используя «Foo < бар» в вашем любимом языке программирования гораздо более эффективным и легким для чтения.)

+0

Вы можете объединить три выражения вы должны получить ни одного, если это то, что вы имеете в виду. – Dervall

ответ

3

You» потребуется генерировать выражение для каждого ограничивающего числа. Предположим, что было регулярное выражение, которое выполнило бы эту работу. Тогда это регулярное выражение должно было бы принимать в качестве входных данных некоторую последовательность символов. Однако мы знаем, что регулярные выражения и автоматы конечного состояния эквивалентны, так что это то же самое, что сказать, что мы можем построить FSM, поскольку возможное число неограничено, что потребует неограниченного числа состояний, что противоречит определению FSA.

+0

А? Вы говорите, что это невозможно, или это действительно забавный способ сказать «да»? Вы намекаете на отрицательные числа, хотя OP явно подразумевает неотрицательное числовое пространство? – tripleee

+0

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

+0

Если OP означает только определенное число, он может сделать это тривиально - перечислить все значения ниже его границы. Тогда, если он чувствует амбициозность, свести к минимуму соответствующий FSM и использовать минимальное регулярное выражение. –

2

Это довольно просто.

#!/usr/bin/env perl 
use strict; 
use warnings; 
use Regexp::Assemble; 

for my $n (@ARGV) { 
    my $asm = new Regexp::Assemble; 
    for (1 .. $n) { $asm->add($_) } 
    for ($asm->re){ 
     s/\)$/\$/; 
     s/^[^:]*:/^/; 
     print "$n => /$_/\n"; 
    } 
} 

Теперь запустите его, чтобы найти модель, которая соответствует целым числам от 1 и этого числа:

$ perl /tmp/ra 5 15 153 401 1144 
5 => /^[12345]$/ 
15 => /^(?:[23456789]|1[]?)$/ 
153 => /^(?:1(?:[6789]|5[0123]?|0\d?|1\d?|2\d?|3\d?|4\d?)?|2\d?|3\d?|4\d?|5\d?|6\d?|7\d?|8\d?|9\d?)$/ 
401 => /^(?:1(?:0\d?|1\d?|2\d?|3\d?|4\d?|5\d?|6\d?|7\d?|8\d?|9\d?)?|2(?:0\d?|1\d?|2\d?|3\d?|4\d?|5\d?|6\d?|7\d?|8\d?|9\d?)?|3(?:0\d?|1\d?|2\d?|3\d?|4\d?|5\d?|6\d?|7\d?|8\d?|9\d?)?|4(?:[123456789]|0[01]?)?|5\d?|6\d?|7\d?|8\d?|9\d?)$/ 
1144 => /^(?:1(?:0(?:0\d?|1\d?|2\d?|3\d?|4\d?|5\d?|6\d?|7\d?|8\d?|9\d?)?|1(?:[56789]|4[]?|0\d?|1\d?|2\d?|3\d?)?|2\d?|3\d?|4\d?|5\d?|6\d?|7\d?|8\d?|9\d?)?|2(?:0\d?|1\d?|2\d?|3\d?|4\d?|5\d?|6\d?|7\d?|8\d?|9\d?)?|3(?:0\d?|1\d?|2\d?|3\d?|4\d?|5\d?|6\d?|7\d?|8\d?|9\d?)?|4(?:0\d?|1\d?|2\d?|3\d?|4\d?|5\d?|6\d?|7\d?|8\d?|9\d?)?|5(?:0\d?|1\d?|2\d?|3\d?|4\d?|5\d?|6\d?|7\d?|8\d?|9\d?)?|6(?:0\d?|1\d?|2\d?|3\d?|4\d?|5\d?|6\d?|7\d?|8\d?|9\d?)?|7(?:0\d?|1\d?|2\d?|3\d?|4\d?|5\d?|6\d?|7\d?|8\d?|9\d?)?|8(?:0\d?|1\d?|2\d?|3\d?|4\d?|5\d?|6\d?|7\d?|8\d?|9\d?)?|9(?:0\d?|1\d?|2\d?|3\d?|4\d?|5\d?|6\d?|7\d?|8\d?|9\d?)?)$/ 
Смежные вопросы