不匹配正则表达式的空字符串

时间:2015-05-29 14:03:56

标签: regex

我正在尝试使用正则表达式来匹配日期(从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,},就像链接中所述的建议一样。

但它没有用。

实际上我并不理解为什么它也匹配空字符串,有人也可以告诉我吗?

4 个答案:

答案 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函数可能更有意义,其目的是验证输入。

验证将是双重的:

  1. 首先,检查提供的字符串是否为空。
  2. 您根据当前使用的表达式验证字符串。
  3. 请注意,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}
相关问题