我正在尝试编写一个正则表达式来匹配和拆分 C# 中的自定义变量语法。这里的想法是字符串值的自定义格式设置,与 .NET String.Format/{0} 字符串格式设置样式非常相似。
例如,用户将定义一个 String 格式以在运行时进行评估,如下所示:
D:\Path\{LanguageId}\{PersonId}\
值“LanguageId”匹配数据对象字段,其当前值替换。
当需要将参数传递给格式化字段时,事情就变得棘手了。例如:
{LanguageId:English|Spanish|French}
如果“LanguageId”的值等于参数之一,这将具有执行某些条件逻辑的意义。
最后我需要像这样支持 map 参数:
{LanguageId:English=>D:\path\english.xml|Spanish=>D:\path\spansih.xml}
这里是所有可能值的枚举:
命令无参数: 做点特别的事
{@Date}
命令单个参数:
{@Date:yyyy-mm-dd}
无参数:
{LanguageId}
单参数列表:
{LanguageId:English}
多参数列表:
{LanguageId:English|Spanish}
单参数映射:
{LanguageId:English=>D:\path\english.xml}
多参数映射:
{LanguageId:English=>D:\path\english.xml|Spanish=>D:\path\spansih.xml}
总结:语法可以归结为带有可选参数类型列表或映射(不是两者)的键。
下面是我目前使用的正则表达式,它有一些问题,即它没有正确处理所有空格,在 .NET 中我没有得到我期望的拆分。例如,在第一个示例中,我返回了“{LanguageId}{PersonId}”的单个匹配项,而不是两个不同的匹配项。此外,我确信它不处理文件系统路径或分隔的带引号的字符串。任何帮助我度过难关的帮助都将不胜感激。或任何建议。
private const string RegexMatch = @"
\{ # opening curly brace
[\s]* # whitespace before command
@? # command indicator
(.[^\}\|])+ # string characters represening command or metadata
( # begin grouping of params
: # required param separater
( # begin select list param type
( # begin group of list param type
.+[^\}\|] # string of characters for the list item
(\|.+[^\}\|])* # optional multiple list items with separator
) # end select list param type
| # or select map param type
( # begin group of map param type
.+[^\}\|]=>.+[^\}\|] # string of characters for map key=>value pair
(\|.+[^\}\|]=>.+[^\}\|])* # optional multiple param map items
) # end group map param type
) # end select map param type
) # end grouping of params
? # allow at most 1 param group
\s*
\} # closing curly brace
";
请您参考如下方法:
您试图用一个正则表达式做太多事情。我建议您将任务分解为多个步骤,首先是对看起来像变量的东西进行简单匹配。该正则表达式可以很简单:
\{\s*([^{}]+?)\s*\}
这会将您的整个变量/命令字符串保存在第 1 组中,减去大括号和周围的空格。之后,您可以根据需要拆分冒号、管道,然后是 "=>" 序列。不要将所有复杂性压缩到一个怪物正则表达式中;如果您设法编写了正则表达式,您会发现以后您的需求发生变化时无法维护。
还有一件事:现在,您专注于让代码在输入正确时运行,但是当用户输入错误时怎么办?您不想给他们有用的反馈吗?正则表达式很烂;他们严格通过/失败。正则表达式非常有用,但与任何其他工具一样,您必须先了解它们的局限性,然后才能充分利用它们。
