首页 > 解决方案 > 正则表达式解析由括号分段的数据

问题描述

我需要一个正则表达式来解析一些由方括号分段的数据。

每个数据包含 3 个部分,固定名称和预设顺序,可以与餐食进行比较。
(部分标识符:<br />[Breakfast]<br />, <br />[Lunch]<br />, <br />[Dinner]<br />

但问题是每个数据的部分或全部部分可能不存在,如下例所示,内容可能包含成对的括号以提供附加信息。
(但从不包含标识符。)

样本数据:


期望的输出:
$date: 20181225
$breakfast: Fish finger sandwich [400 kcal]<br />Jellied eels
$lunch: Pork pies [500 kcal]
$dinner: Stargazy pies

$date: 20181226
$dinner: Stargazy pies

$date: 20181227
$breakfast: Fish finger sandwich [400 kcal]<br />Jellied eels
$dinner: Stargazy pies

$date: 20181228

我在下面尝试了正则表达式,但不能正常工作,因为贪婪的量词会忽略以下部分,即使它们存在

(?<date>\d{8})(?:<br \/>\[Breakfast\]<br \/>(?<breakfast>.*))?(?:<br \/>\[Lunch\]<br \/>(?<lunch>.*))?(?:<br \/>\[Dinner\]<br \/>(?<dinner>.*))?

提前致谢。

标签: c#regex

解决方案


一种选择是,在每个可选组的末尾,在lazy-repeating 之后立即查找$or 。还要将匹配的结尾锚定到字符串的末尾,以确保每个可以匹配的子组都会被匹配:<br.

(?<date>\d{8})(?:<br \/>\[Breakfast\]<br \/>(?<breakfast>.*?(?=$|<br)))?(?:<br \/>\[Lunch\]<br \/>(?<lunch>.*?(?=$|<br)))?(?:<br \/>\[Dinner\]<br \/>(?<dinner>.*))?$
                                                           ^^^^^^^^^^

https://regex101.com/r/vtCLoX/1

如果您不能指望包含该数据的字符串,那么使用$s 将不起作用 - 相反,after Breakfast,在确保您没有遇到的情况下重复Lunch|Dinner,并且 after Lunch,在确保您没有遇到的情况下重复跨越Dinner

(?<date>\d{8})(?:<br \/>\[Breakfast\]<br \/>(?<breakfast>(?:(?!<br \/>\[(Lunch|Dinner)\]).)+))?(?:<br \/>\[Lunch\]<br \/>(?<lunch>(?:(?!<br \/>\[Dinner).)+))?(?:<br \/>\[Dinner\]<br \/>(?<dinner>.*))?
                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                      ^^^^^^^^^^^^^^^^^^^^^^^^^

https://regex101.com/r/vtCLoX/3


推荐阅读