Ответ 1
Отказ от ответственности: Я использую PHP, что означает, что я использую аромат PCRE regex.
Проблема
Кажется, что вы не знаете границ регулярных выражений, но это нормально.
На самом деле вопрос заключается в следующем: проверьте, соответствует ли x =< y
.
Предел
Почему? Ну, вы хотите проверить, если start date =< end date
. Идея регулярных выражений состоит в том, чтобы сопоставить определенные символы после определенного регулярного шаблона. Только в Regex не может проверить, есть ли x < y
, поскольку регулярное выражение не имеет логических операторов >
<
.
Обход определенного предела
То, что regex может сделать, это проверить, есть ли x = y
. Скажем, например, у меня есть следующая строка, и я хочу получить все строки, где x = y
:
10 = 10
15 = 51
33 = 31
100 = 101
780 = 780
Мы можем использовать следующее регулярное выражение: ^(\d+)\s*=\s*\1$
с модификатором m
. Что это значит?
-
^
: начало строки -
(\d+)
: группировать и сопоставлять любую цифру один или несколько раз -
\s*=\s*
: совпадение пробелов 0 или более раз, а затем=
, а затем любое пустое поле 0 или более раз -
\1
: ссылаясь на группу 1, поэтому сопоставляем, только если она такая же, как и в группе 1. -
$
: конец строки -
m
модификатор: многострочный. Сделайте^
и$
совпадение начала и конца строки соответственно
Онлайн-демонстрация.
Доказательство концепции
Позвольте взломать дальше. Для этого POC, мы будем соответствовать следующим: x-y
где 0 =< x =< 9
и 0 =< y =< 9
и x =< y
.
Мы можем попытаться сопоставить все возможности, где x =< y
. Поэтому, если x=0
тогда y=[0-9]
, если x=1
, то y=[1-9]
, если x=2
, тогда y=[2-9]
и т.д. Так как regex имеет оператор or
, мы можем написать следующее регулярное выражение: 0-[0-9]|1-[1-9]|2-[2-9]|3-[3-9]|4-[4-9]|5-[5-9]|6-[6-9]|7-[7-9]|8-[8-9]|9-9
Онлайн-демонстрация
Ты видишь? Это на самом деле так долго для простого сравнения! Поэтому любой здравомыслящий человек будет анализировать и проверять его со встроенными языковыми инструментами.
Нарушение законов регулярного выражения
Мы будем использовать PHP для генерации выражения регулярного выражения:
$start = strtotime('2013-01-01'); // Start date
$end = strtotime('2013-03-01'); // End date
$range = array_map(function($v){return date('Ymd', $v);}, range($start, $end, 86400)); // Creating the range of dates
$result = ''; // Declaring an empty variable to store our regex in it
for($i=$start;$i<=$end;$i+=86400){ // loop each day
$result .= '(?:' . date('Ymd', $i) . '-(?:'. implode('|', $range) . '))|'; // building our regex
array_shift($range); // removing first element of range
}
$result = substr($result, 0, -1); // removing last | since we don't need it
echo $result; // Output
Вышеприведенный код будет генерировать регулярное выражение, которое может проверять дату между 2013-01-01
и 2013-03-01
, где x =< y
в форме x-y
. Это регулярное выражение не оптимизировано и имеет значение 17 КБ. Итак, представьте размер этого регулярного выражения, если я настроил его для проверки диапазона 10 лет? Обратите внимание, что размер растет экспоненциально. Я пробовал с интервалом в 4 месяца, но я получил сообщение об ошибке/предупреждении о том, что выражение слишком велико.
Поскольку регулярное выражение слишком длинное, я не могу сделать его онлайн-демонстрацию, но здесь код в PHP:
$string = '20130101-20130101
20130201-20130101
20130105-20130120
20130201-20130301
20130210-20130215
20130301-20130301
20130301-20130201
'; // A sample
$regex = file_get_contents('regex.txt'); // Get the regex from a file (which we generated previously)
preg_match_all('#'.$regex.'#', $string, $matches); // Let regex !
print_r($matches[0]); // Printing the matches ...
Вывод:
Array
(
[0] => 20130101-20130101
[1] => 20130105-20130120
[2] => 20130201-20130301
[3] => 20130210-20130215
[4] => 20130301-20130301
)
Онлайн-дамп регулярного выражения Онлайн-демонстрация PHP
Заключение
Пожалуйста, никогда не думайте об использовании regex для этой задачи, иначе у вас было бы 10 проблем:)