我设置了一个正则表达式来匹配美国格式的日期和时间。它看起来像这样:
/(\d{1,2})\/(\d{1,2})\/(\d{2,4}) (\d{1,2}):(\d{1,2})(am|pm|AM|PM|Am|Pm)/
但是,我还需要它来匹配不包含时间组件的日期。
我该如何修改它,如果是日期,我会得到 3 个匹配项,如果是日期时间,我会得到 6 个匹配项?
我设置了一个正则表达式来匹配美国格式的日期和时间。它看起来像这样:
/(\d{1,2})\/(\d{1,2})\/(\d{2,4}) (\d{1,2}):(\d{1,2})(am|pm|AM|PM|Am|Pm)/
但是,我还需要它来匹配不包含时间组件的日期。
我该如何修改它,如果是日期,我会得到 3 个匹配项,如果是日期时间,我会得到 6 个匹配项?
使用?
时间正则表达式,带有(?:)
非捕获组的包装器。
/(\d{1,2})\/(\d{1,2})\/(\d{2,4})(?:\s+(\d{1,2}):(\d{1,2})(am|pm|AM|PM|Am|Pm))?/
请注意,文字空间已替换为\s+
.
+
- 匹配 1 个或更多
*
- 匹配 0 个或更多
?
- 匹配 0 或 1
你可以使用这个:
/(\d{1,2})\/(\d{1,2})\/(\d{2,4})(?: (\d{1,2}):(\d{1,2})(am|pm|AM|PM|Am|Pm))?/
甚至缩短您的正则表达式:
/(\d{1,2})\/(\d{1,2})\/(\d{2,4})(?: (\d{1,2}):(\d{1,2})([ap]m))?/i
我将空间和时间包装到一个非捕获组中,并放置一个?
0 或 1 次出现以使时间可选。
字符类[ap]
匹配a
orp
和 ,因为am
and都pm
以 结尾m
,您可以简单地使用[ap]m
and 不区分大小写的修饰符来[ap]m
匹配大写和小写字符。
/(\d{1,2})\/(\d{1,2})\/(\d{2,4})(?: (\d{1,2}):(\d{1,2})(am|pm|AM|PM|Am|Pm))?/
抑制捕获,因此?:
如果时间存在,您最终不会得到额外的组。
aM
此外,如果您对允许and不太挑剔pM
,您可以使用不区分大小写的修饰符大大简化:
/(\d{1,2})\/(\d{1,2})\/(\d{2,4})(?: (\d{1,2}):(\d{1,2})([ap]m))?/i
事实上,使用?
你甚至可以进一步缩短模式,(因为\d?
比 短{1,2}
:
/(\d\d?)\/(\d\d?)\/(\d{2,4})(?: (\d\d?):(\d\d?)([ap]m))?/i
但是请注意,无论如何,您仍将获得 6 组(如果算上整场比赛,则为 7 组)- 只是最后三个将是undefined
:
> groups = '11/11/11'.match(/(\d{1,2})\/(\d{1,2})\/(\d{2,4})(?: (\d{1,2}):(\d{1,2})([ap]m))?/i)
["11/11/11", "11", "11", "11", undefined, undefined, undefined]
exec
代替使用时也会发生同样的情况。但如果需要,这些很容易过滤掉:
> groups.filter(function(capture) {
return typeof capture !== 'undefined';
});
["11/11/11", "11", "11", "11"]
或者在这种情况下(因为你永远不能有空字符串作为捕获):
> groups.filter(function(capture) {
return capture;
});
["11/11/11", "11", "11", "11"]