匹配可选部分的部分

match portions of an optional section

本文关键字:选部      更新时间:2023-09-26

我设置了一个正则表达式来匹配美国格式的日期和时间。 它看起来像这样:

/('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))?/

?:禁止捕获,因此在时间存在时,您最终不会得到额外的组。

此外,如果您对允许 aMpM 不太挑剔,您可以使用不区分大小写的修饰符大大简化:

/('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"]

使用?时间正则表达式,包装器与非捕获组(?:)

/('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]匹配ap,并且由于ampm都以m结尾,因此您可以简单地使用[ap]m和不区分大小写的修饰符来使[ap]m匹配大写和小写字符。