如何在正则表达式中描述可选的负向前瞻?

时间:2015-05-14 09:40:00

标签: regex grep lookahead

我想通过使用grep来获得一个名为khal的程序输出的日历条目的约会描述。 khal的输出如下:

20:30-22:30 13.05.2015: Manfred treffen Repeat: FREQ=WEEKLY;BYDAY=WE;WKST=MO
09.05. - 12.05.2015: Britt Besuch

在示例中,我想匹配Manfred treffenBritt Besuch。但是,正如您所看到的那样,第一个约会是重复约会,并且khal会将这些信息添加到输出中。在这种情况下,正则表达式必须确保将省略以Repeat:开头的每个部分,但当然只有它存在。

grep -oP "(?<=: )(.)+(?=Repeat: .+$)"得到了我 Manfred treffen但不是Britt Besuch

然而grep -oP "(?<=: )(.)+(?=Repeat: .+$|$)"给了我两个约会的描述,但第一个约会与整个&#34;重复:...&#34;部分包括。

我似乎需要一个可选的前瞻。我在stackoverflow上发现了一个类似的问题但是并没有真正理解这种方法(贪婪匹配),也没有可能在我的情况下采用它。

4 个答案:

答案 0 :(得分:3)

要在Repeat:切断匹配,请使用此lookbehind:

(?<=: )(.+)(?= Repeat:|$)

不是将从Repeat:开始的所有内容都匹配到结尾,而只匹配Repeat:,前面有一个空格。换句话说,从您的lookbehind中删除.+$。这足以在名称后停止匹配,产生您期望的结果。

grep -oP '(?<=: ).+(?= Repeat:|$)' file

Demo.

答案 1 :(得分:0)

您不需要在正则表达式中添加repeat,只需在:

日期之后成为捕获组即可
\d+\.\d+\.\d+:\s?(\w+ \w+)

DEMO

但是如果您只想使用:并且您只想要名称和名称是2部分,则可以使用以下正则表达式:

(?<=: )[a-zA-Z]+ [a-zA-Z]+

如果您不知道:之后的姓名长度,可以使用以下正则表达式:

\d+\.\d+\.\d+:\s?(.+)((?= \w+:)|$) 

Demo

答案 2 :(得分:0)

(?m)(?<=(?<!Repeat): ).*?(?=Repeat|$)

你可以尝试一下。参见演示。

https://regex101.com/r/mT0iE7/19

答案 3 :(得分:0)

尝试这个

(?<=\d{4}:).+?(?=Repeat|$)

Demo