在最后一场比赛中开始比赛的懒惰正则表达式最初没有结束

时间:2015-12-28 14:02:22

标签: regex

我正在尝试从半结构化文本中提取数据,它是由制表符分隔表组成的电子邮件。用户在每个表的顶部输入了时间戳,在表中列出了我要查找的安全标识符。

目标是在correctsecurity所在的表格顶部提取correctsecurity和时间戳。

例如......

10:00 AM
not it
not it

9:00 AM
not it
correctsecurity

..应该返回9:00 AM correctsecurity。但是我当前的正则表达式正在返回10:00 AM correctsecurity,这意味着正确的项目,但不是正确的时间。

到目前为止,这是我的正则表达式:

((1[0-2]|[0-9]):[0-5][0-9](\s?(AM|PM))?)(?:(.*\n)+)(correctsecurity)

请注意,最后一部分correctsecurity是根据其他标准动态创建的,所以即使我在这个问题中提供实际项目,它也会提供一些帮助(因为它是众多之一),为简单起见请假设correctsecurity正是我要找的项目。

最后我在VBA中这样做,所以也许在不使用长正则表达式的情况下解决这个问题就更容易了,所以请尽量提出非正则表达式解决方案。

2 个答案:

答案 0 :(得分:0)

你可以用负向前瞻来解决这个问题:

a((?!a).)*correctsecurity

其中a是你想要开始比赛的模式,并且不希望在比赛的中间加入。

适用于您的特定需求:

\d*:\d* [AP]M((?!\d*:\d* [AP]M).)*correctsecurity

不要忘记让点匹配线断开。

我假设VBA使用VBScript正则表达式方言,需要进行以下修改:

\d*:\d* [AP]M((?!\d*:\d* [AP]M)[\s\S])*correctsecurity

答案 1 :(得分:0)

要解决主要问题,只需将正则表达式的中心部分更改为不接受空行:

  

.*\n - > .+\n

然后在中心部分之前添加换行符\n,以避免跳过AM|PM部分:

所以你的正则表达式将是:

((1[0-2]|[0-9]):[0-5][0-9](\s?(AM|PM))?)\n(?:(.+\n)+)(correctsecurity)

                                        ^      ^
Changes --------------------------------|------|

<小时/> 可选优化 您可以删除许多不需要的组,并为换行符(?:\r\n?|\n)添加通用的多操作系统正则表达式:

((?:1[0-2]|[0-9]):[0-5][0-9](?: [AP]M)?)(?:\r\n?|\n)(?:[^\r\n]+(?:\r\n?|\n))+(correctsecurity)