За последние 24 часа нас посетили 15028 программистов и 1766 роботов. Сейчас ищут 1536 программистов ...

Диапозон чисел

Тема в разделе "Регулярные выражения", создана пользователем Alex5646, 19 фев 2016.

  1. Alex5646

    Alex5646 Новичок

    С нами с:
    29 дек 2015
    Сообщения:
    277
    Симпатии:
    4
    Адрес:
    От верлюда
    Не давно меня заинтересовал вопрос как сделать регулярное выражение для проверки диапазона чисел а конкретно года, текущий год - 100 до текущий год - 16. Я начал сначала пробовать строить простые выражения: (0[0-9]|1[0-2]) - 01-12, потом по сложнее (0[1-9]|[1-2][0-9]|3[01]) - 01-31, ну и наконец дело дошло до года (191[6-9]|19[2-9][0-9]|2000) - 1916 - 2000, когда я понял что у меня не получиться сделать подобное на основе текущей даты, а каждый год менять регулярку на новую как то не прикалывает.

    Я написал php функцию которая создаёт регулярку для диапазона чисел:
    Код (PHP):
    1. /**
    2.  * Формирует регулярное выражение
    3.  * для диапазона чисел
    4.  *
    5.  * @param $start - Начальное число
    6.  * @param $finish - Конечное число
    7.  * @param bool $zero - Нужен ведущий ноль? 04 или 4?
    8.  * @return false|string
    9.  */
    10. function rangeRegex($start, $finish, $zero = false)
    11. {
    12.     // Если первое число больше второго
    13.     // или какой то из параметров не
    14.     // являеться число
    15.     if($start >= $finish || ! is_int($start) || ! is_int($finish))
    16.     {
    17.         return false;
    18.     }
    19.  
    20.     $out = '(';
    21.  
    22.     // Цикл по диапазону чисел
    23.     foreach(range($start, $finish) as $number)
    24.     {
    25.         // Если число меньше или
    26.         // равно 9 и если надо добавляем
    27.         // ведущий ноль
    28.         if ($number <= 9 && $zero)
    29.         {
    30.             $out .= 0;
    31.         }
    32.  
    33.         $out .= $number;
    34.  
    35.         // Если число не является
    36.         // последним добавляем разделитель
    37.         if ($number != $finish)
    38.         {
    39.             $out .= '|';
    40.         }
    41.     }
    42.  
    43.     $out .= ')';
    44.  
    45.     return $out;
    46. }
    47.  
    Она делает ужасную вещь генерирует все возможные варианты чисел и перечисляет их через |.

    Начал проверять работу функции:
    Код (PHP):
    1. rangeRegex(1, 12, true);// (01|02|03|04|05|06|07|08|09|10|11|12)
    2. rangeRegex(1, 31, true);// (01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31)
    3. rangeRegex(((int) date('Y')) - 100, ((int) date('Y')) - 16);// o_O   
    Насколько правильный такой подход? И как можно по другому сделать диапазон от ((int) date('Y'))-100 до (int) date('Y'))-16?
     
  2. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.097
    Симпатии:
    1.241
    Адрес:
    там-сям
    регулярка не предназначена для подобных действий. прими это и прости. проверяй обычным способом, как выражение с больше-меньше.
     
  3. runcore

    runcore Старожил

    С нами с:
    12 окт 2012
    Сообщения:
    3.625
    Симпатии:
    158
    я както давно в академических целях писал такую универсальную регулярку)
    получилась большая, но универсальная, для всех чисел года, кроме 29 февраля. ибо тут нужна информация о високостности года. а это уже усложняет регулярку неимоверно.
     
  4. Alex5646

    Alex5646 Новичок

    С нами с:
    29 дек 2015
    Сообщения:
    277
    Симпатии:
    4
    Адрес:
    От верлюда
    А кода не осталось? Было бы интересно посмотреть.
     
  5. runcore

    runcore Старожил

    С нами с:
    12 окт 2012
    Сообщения:
    3.625
    Симпатии:
    158
    вспомнил. вот что получилось тогда, для формата DD-MM-YYYY для дат от 2000 года
    Код (PHP):
    1. /^((0[1-9]|[12]\d)-(0[1-9]|1[012])|30-(0[13-9]|1[012])|31-(0[13578]|1[02]))-2\d{3}$/ 
    Добавлено спустя 4 минуты 32 секунды:еще для проверки даты можно юзать checkdate()
     
  6. Alex5646

    Alex5646 Новичок

    С нами с:
    29 дек 2015
    Сообщения:
    277
    Симпатии:
    4
    Адрес:
    От верлюда
    strtotime() лучше для этого подходит.
    Я думаю не стоит уходить от темы регулярок.
     
  7. runcore

    runcore Старожил

    С нами с:
    12 окт 2012
    Сообщения:
    3.625
    Симпатии:
    158
    зависит от задачи и входных данных.
     
  8. Alex5646

    Alex5646 Новичок

    С нами с:
    29 дек 2015
    Сообщения:
    277
    Симпатии:
    4
    Адрес:
    От верлюда
    Вот мой вариант по сложнее работает с любой датой в диапазоне 1900-2100, и с високосными годами, формат YYYY-MM-DD:
    Код (PHP):
    1. /^(190[48]|(19|20)[13579][26]|19[2468][048]|20[02468][048])-((0[12478]|(10|12))-(0[1-9]|[12][0-9]|3[01])|(02)-(0[1-9]|[12][0-9])|(0[469]|11)-(0[1-9]|[12][0-9]|30))|(19[0-9][0-9]|20[0-9][0-9]|2100)-((0[12478]|10)-(0[1-9]|[12][0-9]|3[01])|(02)-(0[1-9]|[12][0-9])|(0[469]|1[12])-(0[1-9]|[12][0-9]|30))$/ 
    Ладно шучу))) Вот вариант с табуляцей:
    Код (PHP):
    1. /^
    2. (
    3.     (?# Високосные года)
    4.     190[48] | (19|20)[13579][26] | 19[2468][048] | 20[02468][048]
    5. )-(
    6.     (
    7.         (?# Месяцы 1, 2, 4, 7, 8, 10, 12)
    8.         0[12478] | (10|12)
    9.     )-(
    10.         (?# 31 день)
    11.         0[1-9] | [12][0-9] | 3[01]
    12.     )
    13.  
    14.     | (
    15.         (?# Февраль)
    16.         02
    17.     )-(
    18.         (?# 29 дней)
    19.         0[1-9] | [12][0-9]
    20.     )
    21.  
    22.     | (
    23.         (?# Месяцы 4, 6, 9, 11)
    24.         0[469] | 11
    25.     )-(
    26.         (?# 30 дней)
    27.         0[1-9] | [12][0-9] | 30
    28.     )
    29. )
    30.  
    31. | (
    32.     (?# Все года в диапозоне 1900-2100)
    33.     19[0-9][0-9]
    34.     | 20[0-9][0-9]
    35.     | 2100
    36. )-(
    37.     (
    38.         (?# Месяцы 1, 2, 4, 7, 8, 10)
    39.         0[12478] | 10
    40.     )-(
    41.         (?# 31 день)
    42.         0[1-9] | [12][0-9] | 3[01]
    43.     )
    44.  
    45.     | (
    46.         (?# Февраль)
    47.         02
    48.     )-(
    49.         (?# 29 Дней)
    50.         0[1-9] | [12][0-9]
    51.     )
    52.  
    53.     | (
    54.         (?# Месяцы 4, 6, 9, 11, 12)
    55.         0[469] | 1[12]
    56.     )-(
    57.         (?# 30 дней)
    58.         0[1-9] | [12][0-9] | 30
    59.     )
    60. )
    61. $/