Skip to main content
 首页 » 编程设计

c#之用于匹配自定义语法的正则表达式

2024年01月22日24www_RR

我正在尝试编写一个正则表达式来匹配和拆分 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 组中,减去大括号和周围的空格。之后,您可以根据需要拆分冒号、管道,然后是 "=>" 序列。不要将所有复杂性压缩到一个怪物正则表达式中;如果您设法编写了正则表达式,您会发现以后您的需求发生变化时无法维护。

还有一件事:现在,您专注于让代码在输入正确时运行,但是当用户输入错误时怎么办?您不想给他们有用的反馈吗?正则表达式很烂;他们严格通过/失败。正则表达式非常有用,但与任何其他工具一样,您必须先了解它们的局限性,然后才能充分利用它们。