您正在将 Python 语法(or boolean 和 | 按位 OR 运算符)与正则表达式语法混合。
虽然正则表达式确实使用| 来分隔替代模式,但正则表达式中使用的语法与 Python 运算符不同且分开。你不能随意将两者结合起来。正则表达式语法通过字符串传递给 re 模块函数,而不是作为 Python 表达式。
这行得通:
either = r"({}|{})\.(\d+)".format(date28, date29)
res = re.search(either, date)
因为正则表达式模式使用正则表达式语法first组合成单个字符串。
注意这里没有意义使用date28,因为date28可以匹配的所有东西,date29也可以匹配。此外,date28 与 02.19.(有效日期为 2 月)不匹配。
如果您想从“已标记”组件构建正则表达式,我建议您使用re.VERBOSE 标志,这会导致正则表达式(包括换行符)中的空格被忽略,并添加对使用# ... cmets 的支持。要匹配空格,请使用显式类,例如 [ ]、[\n]、\s 等。我也经常将其与显式组名结合使用。
例如你的表达式可以写成:
february_date = re.compile(
r"""
(
02\. # month, always February
( # Leap year
0[1-9] # first 9 days
|
[12][0-9] # remainder from 10 to 29
)
|
02\.
( # regular year
0[1-9] # first 9 days
|
[12][0-8] # remainder 10-18, 20-28
)
)
\.(\d+) # The year
""", flags=re.VERBOSE)
res = february_date.search(date)
这种格式还使您更容易看到您在任一模式的开头匹配02\.,这是相当多余的,当然上面的模式仍然存在[12][0-8]与@冗余的问题987654340@,实际上与 2 月 19 日不匹配。
就我个人而言,我只是使用\d{2}\.\d{2}\.\d{4},然后使用datetime.strptime() 来验证匹配的文本实际上是一个有效的日期。构建一个正则表达式来验证日期是一项艰巨的任务,根本不值得努力。
例如,您尝试构建的模式并未告诉您 2001 年不是闰年,因此 02.29.2001 不是有效日期。但是尝试使用datetime.strptime() 解析它会引发异常,告诉您这不是有效日期:
>>> from datetime import datetime
>>> date = '02.29.2001'
>>> datetime.strptime(date, "%m.%d.%Y")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/_strptime.py", line 458, in _strptime
datetime_date(year, 1, 1).toordinal() + 1
ValueError: day is out of range for month