我正在尝试使用正则表达式来匹配日期(从2000年到1990年)。以下正则表达式完全没问题。
((((^20[02468][048])|(^20[13579][26]))-(((0[13578]|1[02])-(0[1-9]|[12]\d|3[0-1]$))|((0[469]|11)-(0[1-9]|[12]\d|30$))|(02-(0[1-9]|1\d|2[0-9]$)))|((^20\d{2})-(((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]$))|((0[469]|11)-(0[1-9]|[12]\d|30$))|(02-(0[1-9]|1\d|2[0-8]$)))))|0000-00-00){1}
注意:匹配闰年(月份中的#days:31, 30, 29
)或正常年份(月份中的#days:31, 30, 28
)或默认(0000-00-00)
然而它也匹配空字符串。我尝试搜索this one之类的解决方案,但我的方法更复杂,我尝试添加{1,}
,就像链接中所述的建议一样。
但它没有用。
实际上我并不理解为什么它也匹配空字符串,有人也可以告诉我吗?
答案 0 :(得分:1)
将所需属性添加到输入:
<input pattern="(((^20[02468][048])|(^20[13579][26]))-(((0[13578]|1[02])-(0[1-9]|[12]\d|3[0-1]$))|((0[469]|11)-(0[1-9]|[12]\d|30$))|(02-(0[1-9]|1\d|2[0-9]$)))|((^20\d{2})-(((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]$))|((0[469]|11)-(0[1-9]|[12]\d|30$))|(02-(0[1-9]|1\d|2[0-8]$)))))|0000-00-00"
type="text"
required/>
浏览器不会尝试验证没有必需属性的空输入。
http://jsfiddle.net/kyaLhqpu/ vs http://jsfiddle.net/kyaLhqpu/1/
答案 1 :(得分:0)
从input
标记中提取正则表达式并简单地创建一个Javascript函数可能更有意义,其目的是验证输入。
验证将是双重的:
请注意,Javascript的使用可以在使用<
,>
和=
等实际数学运算符执行数值范围验证时具有额外的优势,而不是你现在在做什么如果将来需要,最终结果应该更容易理解和改变。
答案 2 :(得分:0)
我没有直接回答接受空字符串的问题。我认为问题不在于正则表达式 - 无论是原版还是修订版。我认为suggestion dtanders可能正在进行中;您的意见支持。
但是,我认为有简化和改进正则表达式的空间。
正则表达式中有许多不必要的括号,逻辑似乎有点复杂。您检查0000-00-00(实际上是最后一个选项,但到目前为止最短的描述),或“任何闰年的任何有效日期”或“非闰年的任何有效日期”。这导致了重复的一大块正则表达式,用于验证所有不变的月份。
如果您重新构建代码以测试任何月份或任何有效闰日中的有效日期,那么重复次数就会减少。
在Perl中,您可以编写空间不重要的扩展正则表达式,并且正则表达式可以分布在多行上以便于理解。这导致了一个测试脚本,如:
#!/usr/bin/env perl
use strict;
use warnings;
my $rx = qr/
^(
20\d{2} -
( (0[13578] | 1[02]) - (0[1-9] | [12]\d | 3[01])
| ((0[469] | 11) - (0[1-9] | [12]\d | 30))
| (02 - (0[1-9] | 1\d | 2[0-8]))
)
| (^20[02468][048] | ^20[13579][26]) - 02 - 29 # Leap day
| 0000-00-00
)$
/x;
while (<>)
{
chomp;
printf "%s: %s\n", (m/$rx/ ? "PASS" : "FAIL"), $_;
}
如果将正则表达式展平为一行(并删除了注释),则得到:
^(20\d{2}-((0[13578]|1[02])-(0[1-9]|[12]\d|3[01])|((0[469]|11)-(0[1-9]|[12]\d|30))|(02-(0[1-9]|1\d|2[0-8])))|(20[02468][048]|20[13579][26])-02-29|0000-00-00)$
原始正则表达式占用276个字符。扁平化时修订占158。
我调用了脚本regex-hell
并创建了一个文件various-dates
,其中包含各种样本日期。输出是:
PASS: 0000-00-00
FAIL: 0001-00-00
FAIL: 0000-01-00
FAIL: 0000-00-01
FAIL: 2000-00-00
FAIL: 2000-01-00
FAIL: 2000-00-01
PASS: 2000-01-01
PASS: 2000-02-28
PASS: 2000-02-29
PASS: 2001-02-28
FAIL: 2001-02-29
PASS: 2003-03-31
FAIL: 2003-03-32
PASS: 2004-04-30
FAIL: 2004-04-31
PASS: 2005-05-31
FAIL: 2005-05-32
FAIL: 2005-05-00
PASS: 2005-05-01
PASS: 2006-06-30
FAIL: 2006-06-31
PASS: 2007-07-31
FAIL: 2007-07-32
PASS: 2008-08-31
FAIL: 2008-08-32
PASS: 2009-09-30
FAIL: 2009-09-31
FAIL: 2009-09-32
PASS: 2010-10-30
PASS: 2010-10-31
FAIL: 2010-10-32
PASS: 2011-11-30
FAIL: 2011-11-31
PASS: 2012-12-31
FAIL: 2012-12-32
PASS: 2099-01-01
PASS: 2099-12-31
FAIL:
答案 3 :(得分:0)
我认为它不匹配空字符串和neither does Rubular,但无论如何,请为您的正则表达式输入结尾^(?!$)
的锚定负面预测以防止匹配时出现空白:
^(?!$)((((^20[02468][048])|(^20[13579][26]))-(((0[13578]|1[02])-(0[1-9]|[12]\d|3[0-1]$))|((0[469]|11)-(0[1-9]|[12]\d|30$))|(02-(0[1-9]|1\d|2[0-9]$)))|((^20\d{2})-(((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]$))|((0[469]|11)-(0[1-9]|[12]\d|30$))|(02-(0[1-9]|1\d|2[0-8]$)))))|0000-00-00){1}