Regex是否使用C#,VB.NET,Perl或任何语言。所以,不管你使用什么语言,与我们分享一两个具有挑战性的正则表达式。
重写这个怪物:
^(?:(?:(?:0?[13578]|1[02])(\/|-|\.)31)\1|(?:(?:0?[13-9]|1[0-2])(\/|-|\.)(?:29|30)\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:0?2(\/|-|\.)29\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:(?:0?[1-9])|(?:1[0-2]))(\/|-|\.)(?:0?[1-9]|1\d|2[0-8])\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$
更易读/可维护:
require 5.010; my $sep = qr{ [/.-] }x; #allowed separators my $any_century = qr/ 1[6-9] | [2-9][0-9] /x; #match the century my $any_decade = qr/ [0-9]{2} /x; #match any decade or 2 digit year my $any_year = qr/ $any_century? $any_decade /x; #match a 2 or 4 digit year #match the 1st through 28th for any month of any year my $start_of_month = qr/ (?: #match 0?[1-9] | #Jan - Sep or 1[0-2] #Oct - Dec ) ($sep) #the separator (?: 0?[1-9] | # 1st - 9th or 1[0-9] | #10th - 19th or 2[0-8] #20th - 28th ) \g{-1} #and the separator again /x; #match 28th - 31st for any month but Feb for any year my $end_of_month = qr/ (?: (?: 0?[13578] | 1[02] ) #match Jan,Mar,May,Jul,Aug,Oct,Dec ($sep) #the separator 31 #the 31st \g{-1} #and the separator again | #or (?: 0?[13-9] | 1[0-2] ) #match all months but Feb ($sep) #the separator (?:29|30) #the 29th or the 30th \g{-1} #and the separator again ) /x; #match any non-leap year date and the first part of Feb in leap years my $non_leap_year = qr/ (?: $start_of_month | $end_of_month ) $any_year/x; #match 29th of Feb in leap years #BUG: 00 is treated as a non leap year #even though 2000,2400,etc are leap years my $feb_in_leap = qr/ 0?2 #match Feb ($sep) #the separtor 29 #the 29th \g{-1} #the separator again (?: $any_century? #any century (?: #and decades divisible by 4 but not 100 0[48] | [2468][048] | [13579][26] ) | (?: #or match centuries that are divisible by 4 16 | [2468][048] | [3579][26] ) 00 ) /x; my $any_date = qr/$non_leap_year|$feb_in_leap/; my $only_date = qr/^$any_date$/;