繁体   English   中英

正则表达式匹配 2 个重复值之间的所有内容

[英]Regex Matching everything between 2 repeating values

我正在制作一个提醒应用程序,我希望能够支持 iCalender 导入。 这就是为什么我希望能够提取事件。 这是 iCalender 中事件的基本格式:

BEGIN:VEVENT
......
......
END:VEVENT

所有这些事件都在一个文件中,所以我会有一个像这样的大列表:

BEGIN:VEVENT
......
......
END:VEVENT
BEGIN:VEVENT
......
......
END:VEVENT

这些事件将有开始日期和结束日期

BEGIN:VEVENT
......
DTSTART;VALUE=DATE:20160402
DTEND;VALUE=DATE:20160403
......
END:VEVENT

当试图只提取事件时,它并不总是相同的格式。 开始日期和结束日期可以在其他特定字段之前或之后。

目前我有:

/BEGIN:VEVENT[\s\S]*?DTSTART;VALUE=DATE:20160402[\s\S]*?END:VEVENT/

但是,这不仅仅匹配事件本身,它从BEGIN:VEVENT的第一场比赛开始匹配,匹配直到日期的所有内容,然后在以下END:VEVENT结束比赛。

因此,在一些事件中,试图匹配它们的列表包括许多其他事件。 有没有办法可以匹配DTSTART;VALUE=DATE:并且只有前一个最近的BEGIN:VEVENT和以下END:VEVENT只是为了提取当天的单个事件?

这个问题可以用一个温和的贪婪令牌来解决,它可以用来获得文本中两个子字符串之间可能的最小窗口。 由于您的文本是多行的,因此您不能使用. atom 要匹配任何字符,您需要使用[^][\\s\\S]

所以,使用

/BEGIN:VEVENT((?:(?!\b(?:END|BEGIN):VEVENT\b)[\s\S])*DTSTART;VALUE=DATE:20160402[\s\S]*?)END:VEVENT/g

查看正则表达式演示

(?:(?!\\b(?:END|BEGIN):VEVENT\\b)[\\s\\S])*部分匹配不是BEGIN:VEVENTEND:VEVENT任何文本(由于\\b字边界)。

 var re = /BEGIN:VEVENT((?:(?!\\b(?:END|BEGIN):VEVENT\\b)[\\s\\S])*DTSTART;VALUE=DATE:20160402[\\s\\S]*?)END:VEVENT/g; var str = 'BEGIN:VEVENT\\n......\\n......\\nEND:VEVENT\\nBEGIN:VEVENT\\n......\\n......\\nEND:VEVENT\\nThese events will have a start date and an end date\\n\\nBEGIN:VEVENT\\n......\\nDTSTART;VALUE=DATE:20160402\\nDTEND;VALUE=DATE:20160403\\n......\\nEND:VEVENT'; var res = []; while ((m = re.exec(str)) !== null) { res.push(m[0]); } document.body.innerHTML = "<pre>" + JSON.stringify(res.map(x => x.replace(/\\r?\\n/g, "<br/>")), 0, 4) + "</pre>";

请注意[\\s\\S]*? 也可以用上面的tempered greedy token代替,但似乎没有必要,因为VEVENT块是良构的,并且没有嵌套的VEVENT块。 如果有嵌套的 VEVENT 块,则[\\s\\S]*? 应替换为温和的贪婪令牌。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM