Regex 使用正则表达式验证出生日期

Regex 使用正则表达式验证出生日期,regex,pattern-matching,Regex,Pattern Matching,我的问题:我发现这个练习很有挑战性。我有点记不清出生日期了 "^[a-z]{1,10}$", // First name "^[a-z]$", // Middle initial "^[a-z']{2,10}$", // Last name 挑战:尝试使用正则表达式验证以下文本字符串(不要担心大小写不敏感): 名字-应由标准英文字母组成,长度在1到10个字符之间 中间首字母-应由标准英文字母组成,长度仅为一个字符 姓氏-应由标准英文字母加上撇号组成,长度在2到

我的问题:我发现这个练习很有挑战性。我有点记不清出生日期了

   "^[a-z]{1,10}$",  // First name
   "^[a-z]$",        // Middle initial
   "^[a-z']{2,10}$", // Last name
挑战:尝试使用正则表达式验证以下文本字符串(不要担心大小写不敏感):

  • 名字-应由标准英文字母组成,长度在1到10个字符之间
  • 中间首字母-应由标准英文字母组成,长度仅为一个字符
  • 姓氏-应由标准英文字母加上撇号组成,长度在2到10个字符之间
  • 出生日期-应介于1900年1月1日和2099年12月31日之间,并且应为以下日期格式之一:dd/mm/yyyy、dd-mm-yyyy或dd.mm.yyyy
  • 我能说出前三个名字。但是我被困在出生日期上了

       "^[a-z]{1,10}$",  // First name
       "^[a-z]$",        // Middle initial
       "^[a-z']{2,10}$", // Last name
    

    请帮帮我

    对于出生日期,在字符串的开头匹配,然后对于月份部分,有一个捕获组匹配01、02、03、04、05、06、07、08、09、10、11或12中的一个,然后是另一个捕获组匹配-/

    /^((1[0-2])|[1-9])[/-.](3[0-1]|[1-2]\d|[1-9])[/-.][19|20]\d{2}$/
    
    对于日部分,您需要捕获组以匹配01、02、…29、30或31中的一个,然后捕获组以匹配-、/或

    出生日期:

      "^(0[1-9]|1[012])[-/.](0[1-9]|[12][0-9]|3[01])[-/.](19|20)\\d\\d$" 
    

    这里有几个项目需要处理:

  • 仅验证日、月和年值的适当值
  • 验证正确的元件是否位于正确的位置
  • 正在验证分隔符是否匹配
  • 确认这是一个实际日期
  • 第一种可能是分组和或。例如,可以将1-12之间的所有值与以下值匹配:

    (?:0[1-9]|1[012])
    
    1900年至2099年

    (?:19|20)\d\d
    
    第二点只是将模式的适当部分放在正确的位置

    第三部分可以通过反向引用完成。首先,您有一个子组来匹配分隔符,如下所示:

    ([\/.-])
    
    接下来,你需要确保在比赛中再次获得相同的角色。这是通过指定一个反斜杠,后跟组的编号来完成的。例如:

    \1
    
    最后,我们要确保没有人指定1925年6月31日或1994年2月30日。在regex中实现这一点绝对是可怕的,应该会很快让我们陷入困境。正则表达式不是解决这个问题的正确方法。 撇开这一点不谈,我们可以用一个正则表达式来解决前三个部分,它看起来像:

    ^(?:0[1-9]|[12]\d|3[01])([\/.-])(?:0[1-9]|1[012])\1(?:19|20)\d\d$
    

    注意?:使一些分组不获得子匹配,这样我们只需要处理我们感兴趣的子匹配。不是严格要求的,但它更清楚。如果不考虑这些,分隔符将是第二个子组,而不是第一个子组。

    对于日期的正则表达式,请参阅链接:

    但我认为这个例子会奏效

      "^(0[1-9]|1[012])[-/.](0[1-9]|[12][0-9]|3[01])[-/.](19|20)\\d\\d$" 
    
     "^(0[1-9]|1[012])[-/.](0[1-9]|[12][0-9]|3[01])[-/.](19|20)\\d\\d$" 
    
    试一试


    对于出生日期,在字符串开头匹配,然后对于月份部分,您有一个捕获组匹配01、02、03、04、05、06、07、08、09、10、11或12中的一个,然后是另一个捕获组匹配-/

    我认为这个例子会奏效

      "^(0[1-9]|1[012])[-/.](0[1-9]|[12][0-9]|3[01])[-/.](19|20)\\d\\d$" 
    
     "^(0[1-9]|1[012])[-/.](0[1-9]|[12][0-9]|3[01])[-/.](19|20)\\d\\d$" 
    
    试试这个

    /^([0-2^([0-2][0-9]|(3)[0-1])(\/)(((0)[0-9])|((1)[0-2]))(\/)\d{4}$/
    

    @科恩武夫有一个很好的解释,我自然选择了它。 但实际上存在一个错误,应修复为:

    /^(?:0[1-9]|[12]\d|3[01])([\/.-])(?:0[1-9]| 1[012])\1(?:19 | 20)\d\d$/
    
    否则,如果月份为
    10
    ,则日期将不会生效

    更改位于
    (?:0[1-9]| 1[012])
    ,您应在此处阅读:

    • (?:)
      是非捕获组(允许表达式)
    • 0[1-9]
      允许
      0
      后跟1到9的数字
    • 1[012]
      允许
      1
      后跟数字0、1或2之一
    • 两者之间的
      |
      表示“或”

    希望有帮助。

    这是如何防止2010年10月10日的呢?它没有。但是您需要编写一个非常长且难看的正则表达式来防止这种情况。或者使用(假设引擎支持它们)请求的格式是
    dd/mm/yyyy
    而不是
    mm/dd/yyyy
    。它还与
    02/31/1900
    这如何防止2010年10月10日?请求的格式是
    dd/mm/yyyy
    而不是
    mm/dd/yyyy
    。此外,它还与日期格式的要求相匹配,这些要求有点混乱。在为可接受范围命名的日期中,您的月份位于日期之前(由12/31表示),但在日期格式中,日期优先。此外,最早的日期(1900年1月1日)写为d/m/yyyy。正则表达式是否也需要匹配月份和日期的单个数字值,或者这个日期显示为1900年1月1日?就在昨天,我写了一篇关于匹配正则表达式的数字范围的博文,这适用于你问题的年份部分(尽管,我承认,1900到2099是相当容易的,正如你在一些回答中所说的):这不是小事,请在这里查看我的答案:请添加一些您正在做的解释。请求的格式是
    dd/mm/yyyy
    而不是
    mm/dd/yyyy
    。此外,它还匹配
    02/31/1900
    请求的格式是
    dd/mm/yyyy
    而不是
    mm/dd/yyyy
    。它还与
    02/31/1900
    相匹配,感谢您提供此代码片段,它可能会提供一些有限的即时帮助。通过展示为什么这是一个很好的问题解决方案,A将极大地提高它的长期价值,并将使它对未来有其他类似问题的读者更有用。请在你的回答中添加一些解释,包括你所做的假设。我非常喜欢这个解释。正则表达式的月份部分应该是(?:0[1-9]| 1[0-2]),而不是(?:0[1-9]| 1[12])。谢谢,@kalyan。固定为不遗漏10月。:)