RegEx 非贪婪量词 .*?没有按预期工作
RegEx non-greedy quantifier .*? not working as expected
我正在尝试创建一个正则表达式来匹配以下字符串中的“section 2 foo 2019 foo”(一个最小的例子,不是真实的):
section 1 bar bar section 2 foo 2019 foo section 3 bar 2021 bar end
(字符串“section”,后跟数字,后跟任何文本,后跟 4 位数年份,再后跟任何文本)
我最初的想法是使用非贪婪量词和一个捕获组和一个非捕获组,如下所示:
(section [0-9]{1}.*?(19|20)[0-9]{2}.*?)(?:section)
但是,这将为捕获组生成以下匹配项:
section 1 bar section 2 foo 2019 foo
所以,它也匹配第 1 部分,我想排除它。
经过一些背景阅读,我明白这里的问题是“非贪婪”实际上并不意味着“匹配最短的字符串”,而是“匹配从左到右读取的最短的字符串”没有回溯。
关于这个问题,这里有一些关于 SO 的答案,但我仍在努力为这个特定案例找到正确的正则表达式。我尝试使用具有负前瞻性的非捕获组,如下所示:
section [0-9]{1,2}(?:(?!section [0-9]{1}).).*(?!202[1-9]{1})[0-9]{4} .*?
但是出乎意料的是,这仍然会匹配第一个不需要的部分。
知道我的想法可能哪里错了吗?
这里的问题是,对“任何”文本部分使用 .*?
仍然有可能匹配匹配或不匹配的部分,直到找到结束年份。您尝试使用调和点的最终正则表达式是在正确的轨道上。考虑这个版本:
\bsection \d+ (?:(?!\bsection \d+).)*?(?:19|20)\d{2}\b
解释:
\bsection \d+ match "section" followed by a number and space
(?:(?!\bsection \d+).)*? match any content, without crossing over to another section
(?:19|20)\d{2}\b match a 4 digit year
我正在尝试创建一个正则表达式来匹配以下字符串中的“section 2 foo 2019 foo”(一个最小的例子,不是真实的):
section 1 bar bar section 2 foo 2019 foo section 3 bar 2021 bar end
(字符串“section”,后跟数字,后跟任何文本,后跟 4 位数年份,再后跟任何文本)
我最初的想法是使用非贪婪量词和一个捕获组和一个非捕获组,如下所示:
(section [0-9]{1}.*?(19|20)[0-9]{2}.*?)(?:section)
但是,这将为捕获组生成以下匹配项:
section 1 bar section 2 foo 2019 foo
所以,它也匹配第 1 部分,我想排除它。
经过一些背景阅读,我明白这里的问题是“非贪婪”实际上并不意味着“匹配最短的字符串”,而是“匹配从左到右读取的最短的字符串”没有回溯。
关于这个问题,这里有一些关于 SO 的答案,但我仍在努力为这个特定案例找到正确的正则表达式。我尝试使用具有负前瞻性的非捕获组,如下所示:
section [0-9]{1,2}(?:(?!section [0-9]{1}).).*(?!202[1-9]{1})[0-9]{4} .*?
但是出乎意料的是,这仍然会匹配第一个不需要的部分。 知道我的想法可能哪里错了吗?
这里的问题是,对“任何”文本部分使用 .*?
仍然有可能匹配匹配或不匹配的部分,直到找到结束年份。您尝试使用调和点的最终正则表达式是在正确的轨道上。考虑这个版本:
\bsection \d+ (?:(?!\bsection \d+).)*?(?:19|20)\d{2}\b
解释:
\bsection \d+ match "section" followed by a number and space
(?:(?!\bsection \d+).)*? match any content, without crossing over to another section
(?:19|20)\d{2}\b match a 4 digit year