首页 > 解决方案 > Ruby Regex:如何在方括号内匹配(命名)组?

问题描述

我正在尝试用 Ruby 编写一个正则表达式来解析各种日期/时间格式。整个正则表达式如下所示:

/^(?<year>\d{4})\-(?<month>\d{2})\-(?<day>\d{2})(T(?<hour>\d{2})(:(?<minute>\d{2})(:(?<second>\d{2}(\.\d{1,3})?))?)?)?(?<offset>[+-]\d{2}:\d{2})?$/

我正在使用命名组,这样我就可以使用“年”、“月”、“日”等简单名称从匹配对象中提取匹配的部分。这个正则表达式运行良好,但让我们专注于在此结束时的“偏移量”:

(?<offset>[+-]\d{2}:\d{2})?

问题是我试图在字符串末尾添加解释“Z”以表示 UTC 时间(又名祖鲁时间)的能力。这个“Z”应该与偏移量互斥。以下是我尝试过的一些方法:

(?<offset>[Z([+-]\d{2}:\d{2})])?
(?<offset>[(Z)([+-]\d{2}:\d{2})])?
[(?<zulu>Z)(?<offset>[+-]\d{2}:\d{2})]?

这些都不起作用。在前两种情况下,它可以解释以“Z”结尾的日期字符串,但不能再解释以“-07:00”等实际偏移量结尾的日期字符串。在第三种情况下,匹配对象中完全缺少命名组“zulu”和“offset”。

我认为这个问题是因为我正在尝试使用方括号来表示[(ThisGroup)(OrThisGroup)]?,但我认为正则表达式引擎不喜欢在方括号内包含组。我如何告诉正则表达式引擎允许和捕获“A 组或 B 组或两者都没有,但不能同时捕获”?

标签: rubyregexoptionalcapturebrackets

解决方案


方括号用于“这些字符中的任何一个”——这不是你需要的。模式级别的交替是通过|运算符完成的:(hello|goodbye) world将匹配hello worldor goodbye world

(?<offset>Z|[+-]\d{2}:\d{2})?

但是,特别是要解析日期时间,我建议更喜欢DateTime.parse(加上to_time,如果您需要 Time 实例)。如果这不够灵活,请考虑慢性宝石。


推荐阅读