首页 文章

复杂正则表达式查找日期和时间

提问于
浏览
0

有人帮我解决以下问题:

我正在尝试在文本中找到特定的日期和时间字符串(在VBA Word中使用) . 目前使用以下RegEx字符串:

(?:( [0-9] {1,2})[| - ])?(?:( jan(?:uari)?| feb(?:ruari)?| m(?:aa)?rt |四月(?:IL)|?梅|君:|七月(我?)?|八月(我?)?(?:ustus)|九月?(?:tember | T)|十月(?:奥伯)?| nov(?:ember)?| dec(?:ember)?))?(?:| - )?(?(3)(?:around | at |))?(?:( [0- 9] {1,2}:[0-9] {1,2})?(?:uur | u | u)?)?

以下文本的测试输出:

  • 约会时间:2016年6月26日09:00左右

  • 与时间:2016年1月1日09:00

  • 日期和时间u:1 sep 2018 09:00 u

  • 没有约会的时间:08:30 uur

  • 日期与时间u:1 sep 2016 at 09:00u

  • 只有时间:09:00

  • 只有一个月:1月

  • 月和年:2019年2月

  • 只有一天:02

  • 只有'-'日:2-

  • 日和月:2月1日

  • 月:2018年1月

  • 与'-'约会:2-feb-2018 09:00

  • 其他月份:2016年9月1日

  • 整月:2018年9月1日

  • 缩短的一年:jul '18

Rules:

  • 日期后跟时间有效

  • 日期后跟文本'around'或'at',后跟时间有效

  • 没有日期编号的日期有效

  • 没有年份的日期有效

  • 日期,月份只有 not 有效

  • 一天,没有月份或年份 not 有效

  • 日期可能包含破折号'-'

  • 一年可能与'短缺',如 jun '18

  • 月份名称可以是短或长

  • 完整匹配包括' uur'或'u'(以突出显示ms-Word中的文本)
    来自捕获的

  • 子匹配文本没有前置空格或尾随空格

例如:[https://regex101.com/r/6CFgBP/1/]

Expected output (when using in VBA Word): 正则表达式匹配集合对象,其中每个Match.SubMatches包含正则表达式搜索字符串中捕获组的各个项目d,m,y,hh:mm . 例如1:子匹配(或捕获组)包含值:'26' ',' sep ',' 2016 ',' 09:00'

RegEx工作正常,但需要排除一些误报:

  • 如果有一天没有月/年,应该从正则表达式中排除(例9和10)

  • 如果有一个月没有白天,应排除(例7)

(我尝试使用som lookahead并引用\ 1和?(1),但无法使其正常运行......)

任何建议高度赞赏!

2 回答

  • 0

    据我了解,您需要 each 日期/时间部分(日,月,年,小时和分钟) must 存在 .

    因此,您应该在相关组之后删除 ? (它们是 not 可选) .

    将每个组捕获为相关的 capturing group 也是一种很好的做法 .

    没有必要写像 jun(?:i)? 之类的东西 . 只写 juni?? 仅指前面的 i )就足够了(并且更容易阅读) .

    另一个提示:由于正则表达式语言包含 \d char类,因此使用它而不是 [0-9] (正则表达式更短且更易于阅读 .

    可选部分(at / around)应该是可选的非捕获组 .

    正则表达式中不需要任何事后的部分 .

    所以我建议使用下面的正则表达式(为了便于阅读,我把它分成了几行):

    (\d{1,2})[ -](jan(?:uari)?|feb(?:ruari)?|m(?:aa)?rt|apr(?:il)?|mei|juni?
    |juli?|aug(?:ustus)?|sep(?:tember|t)?|okt(?:ober)?|nov(?:ember)?|dec(?:ember)?)
    [ -](\d{4}) (?:around |at )?(\d{1,2}:\d{1,2})
    

    细节:

    • (\d{1,2}) - 日 .

    • [ -] - 一天后的分隔符(空格或减号) .

    • (jan(?:uari)?|...dec(?:ember)?) - 月 .

    • [ -] - 月份后的分隔符 .

    • (\d{4}) - 年 .

    • (?:around |at )? - 实际上,年份和小时之间的分隔符的3种变体(空格/大约/ at),请注意(......)之前的空格 .

    • (\d{1,2}:\d{1,2}) - 小时和分钟 .

    它匹配变体1,2,3,5和13.所有剩余的都不能包含每个必需的部分,因此它们不匹配 .

    如果您允许,例如小时/分钟部分是可选的,将相应的片段更改为:

    ( (?:around |at )?(\d{1,2}:\d{1,2}))?
    

    即用 ()? 围绕空间/周围/ at /小时/分钟部分,使该部分成为可选组 . 然后,变体14和15也将匹配 .

    还有一个扩展名:如果您还允许小时/分钟部分 alone ,请将 |(\d{1,2}:\d{1,2}) 添加到正则表达式中(所有之前是第一个变体,而添加的部分是第二个变体,仅适用于小时/分钟 .

    然后,您的变体No 4和6也将匹配 .

    有关工作示例,请参阅https://regex101.com/r/33t1ps/1

    编辑

    根据您的规则列表,我提出以下正则表达式:

    • (\d{1,2}[ -])? - 日分隔符,可选 .

    • (jan(?:uari)?|...|dec(?:ember)?) - 月 .

    • (?:[ -](\d{4}|'\d{2}))? - 分隔年份(带有"'"的4位或2位数字) .

    • ( (?:around |at )?(\d{1,2}:\d{1,2}))? - 分隔符小时/分钟 - 变量1的可选结尾 .

    • |(\d{1,2}:\d{1,2}) - 变式2 - 只有小时和分钟 .

    它只与您的9号和10号变种不匹配 .

    完全正则表达式,包括"uur"见https://regex101.com/r/33t1ps/3

  • 0

    最后我找到了一些可以帮助我正确使用月份的东西:-)

    \b(?:([1-3]|[0-3]\d)[ |-](?'month'(?:[1-9]|\d[12])|(?:jan(?:uari)?|feb(?:ruari)?|m(?:aa)?rt|apr(?:il)?|mei|jun(?:i)?|jul(?:i)?|aug(?:ustus)?|sep(?:tember|t)?|okt(?:ober)?|nov(?:ember)?|dec(?:ember)?))?)?(?:(\g'month')[ |-]((?:19|20|\')(?:\d{2})))?\b(?: omstreeks | om | )?(?:(\d{1,2}[:]\d{2}(?: uur|u)?|[0-2]\d{3}(?: uur|u)))?\b

    它使用命名的构造函数/子例程 . 在这里找到:https://www.regular-expressions.info/subroutine.html

相关问题