所以我需要从这些条目中获得数小时,分钟和秒钟:
前两个是小时,分钟和秒。 接下来是分钟和秒。 最后两个只是秒。
我想出了这个正则表达式,它有效..:
\A(?<hours>\d{1,2})(?::|\.)(?<minutes>\d{1,2})(?::|\.)(?<seconds>\d{1,2})\z|\A(?<minutes>\d{1,2})(?::|\.)(?<seconds>\d{1,2})\z|\A(?<seconds>\d{1,2})\z
但它很丑陋,我想重构它不是3种不同的表达方式(大多数只是为了学习)。我试过这个:
\A(?:(?<hours>\d{1,2})(?::|\.){0,1})(?:(?<minutes>\d{1,2})(?::|\.){0,1})(?:(?<seconds>\d{1,2}){0,1})\z
但这不起作用 - 分钟和秒钟有时会搞砸。我的大脑受伤了,我无法弄明白,我做错了什么。
答案 0 :(得分:10)
我的建议:
(?:(?:(?<hh>\d{1,2})[:.])?(?<mm>\d{1,2})[:.])?(?<ss>\d{1,2})
结构:
(?: # group 1 (non-capturing)
(?: # group 2 (non-capturing)
(?<hh>\d{1,2}) # hours
[:.] # delimiter
)? # end group 2, make optional
(?<mm>\d{1,2}) # minutes
[:.] # delimiter
)? # end group 1, make optional
(?<ss>\d{1,2}) # seconds (required)
如果您愿意,可以将正则表达式包装在分隔符中 - 例如单词边界\b
或字符串锚点(^
和$
)。
编辑:考虑一下,你可以进一步限制它,以捕捉有意义的时间。使用
[0-5]?\d
取代
\d{1,2}
仅在适当的情况下(秒和分钟)捕获0到59之间的值。
答案 1 :(得分:5)
我还没有对此进行测试,但它应该有效:
^(?:(?:(?<hours>\d\d?)[:\.])?(?<minutes>\d\d?)[:\.])?(?<seconds>\d\d?)$
编辑:
现在我测试了它并验证它是否有效。 :)
答案 2 :(得分:2)
我建议使用以下表达式。
^(((?<Hour>[0-9]{1,2})[.:])?(?<Minute>[0-9]{1,2})[.:])?(?<Second>[0-9]{2})$
这将允许单个数字小时与单个数字分钟相结合,如3:7:21
。如果不需要,则需要稍作修改。
^(((?<Hour>[0-9]{1,2})[.:](?=[0-9]{2}))?(?<Minute>[0-9]{1,2})[.:])?(?<Second>[0-9]{2})$
第二个表达式中的正向前瞻断言(?=[0-9]{2})
解决了这个问题。
答案 3 :(得分:1)
对此没有真正好的方法,因为它实际上取决于您的特定情况,当未指定所有三个部分时该怎么做。例如,在许多情况下,我可能更喜欢将3:30解释为3小时30分钟而不是3分30秒。它可以不明白这一点,并且很容易从正则表达式推导出这些输入意味着什么。
因此,我个人认为第一个正则表达式并不是那么难看 - 它可能不那么“神奇”,但它更具可读性和可维护性。确保您和其他人以后仍然可以阅读并更改代码!
如果您的语言支持,我会使用扩展的正则表达式(支持空格和注释)并将其拆分为三行(如果您在单独的行上放置注释,则为6或9)。这不会改变正则表达式,但肯定会让它感觉不那么难看。