免责声明:我使用的是 PHP,这意味着我使用的是 PCRE 正则表达式风格。
问题
似乎您没有意识到正则表达式的局限性,但这没关系。
真正的问题是以下解决方案:检查是否x =< y
匹配。
极限
为什么 ?好吧,您要检查是否start date =< end date
. 正则表达式的思想是按照某种正则模式匹配某些字符。单独的正则表达式无法检查是否x < y
因为正则表达式没有逻辑运算符>
<
。
绕过一定的限制
正则表达式可以做的是检查是否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
where0 =< x =< 9
和。我们能做的是尝试匹配所有可能的位置。所以如果那么,如果那么,如果那么等等。由于正则表达式有语句,我们可以编写以下正则表达式:Online demo
你看到了吗?一个简单的比较实际上太长了!这就是为什么任何理智的人都会使用内置语言工具对其进行解析和验证的原因。0 =< y =< 9
x =< y
x =< y
x=0
y=[0-9]
x=1
y=[1-9]
x=2
y=[2-9]
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
. 此正则表达式未优化,约为17KB。那么想象一下,如果我将它配置为验证 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's 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 演示
结论
请不要考虑使用正则表达式来完成此任务,否则您将遇到 10 个问题 :)