将找到的子字符串提取到变量的模式匹配

Pattern matching with extraction of found substrings to variables

我有一些定义格式的字符串,例如 Foo.<Whatever>.$(Something),我想将它们分成几部分,并将每个部分自动分配给一个变量。

我曾经用 C# 类 和运算符重载写过类似于 bash/shell 管道命令选项“<”的东西。用法类似于

ParseExpression ex = pex("item1") > ".<" > pex("item2") > ">.$(" > pex("item3") > ")";
ParseResult r = new ParseResult(ex, "Foo.<Whatever>.$(Something)");

ParseResult 然后有一个字典,其中键 item1 到 item3 设置为在给定字符串中找到的字符串。方法 pex 生成了一些可以与 > 运算符一起使用的对象,最终具有构成 ParseExpression.

的 ParseExpressionParts 链

我手头没有代码,在我再次从头开始编码之前,我想我最好问问是否有人已经完成并发布了它。

解析表达式让我想起了 parser combinators,例如 Parsec 和 FParsec(对于 F#)。语法会有多复杂?实际上,它可以由带组的正则表达式处理。

如果您想使用解析器组合器创建更复杂的语法,您可以使用 FParsec, one of the better known parser combinators, targeting F#. In general, functional languages like F# are used a lot in such situations. CSharp-monad 是一个针对 C# 的解析器组合器。虽然该项目不是很活跃。

您还可以使用像 ANTLR 4 这样的成熟的解析器生成器。 ASP.NET MVC 使用 ANTLR 来解析 Razor 语法视图。 ANTLR 4 创建一个解析树,并允许您使用类似于 DOM 或 SAX 处理的访问者或侦听器来处理它。一旦遇到元素,侦听器就会调用您的代码(例如开头<、内容等),而访问者则在完成的树上工作。

ANTLR 的 Visual Studio 扩展将为您的语法生成解析器 类 以及基础访问者和侦听器 类。基于 NetBeans 的 ANTLRWorks IDE 使创建和测试语法变得非常容易。

您的示例的粗略语法是:

format: tag '.' '<' category '>' '.' '$' '(' value ')';
tag      : ID;
category : ID;
value    : ID;

ID       :[A-Z0-9]+;

或者您可以定义像 FOO : 'FOO' 这样对您的语法有特殊意义的关键字。访问者或听众可以处理标签,例如格式化字符串、对值执行操作等。

没有硬性规定。就个人而言,我将正则表达式用于更简单的情况,例如处理相对简单的日志文件,而 ANTLR 用于更复杂的情况,如屏幕抓取大型机数据。我没有研究解析器组合器,因为我从来没有时间熟悉 F#。尽管处理一些乱七八糟的 log4net 日志文件,它们真的很方便

我从 Heinzi 的建议开始,最终得出以下代码:

const string tokenPrefix = "px";
const string tokenSuffix = "sx";
const string tokenVar = "var";

string r = string.Format(@"(?<{0}>.*)$\((?<{1}>.*)\)(?<{2}>.*)",
                         tokenPrefix, tokenVar, tokenSuffix);
Regex regex = new Regex(r);
Match match = regex.Match("Foo$(Something)Else");

if (match.Success)
{
  string prefix = match.Groups[tokenPrefix].Value; // = "Foo"
  string suffix = match.Groups[tokenSuffix].Value; // = "Something"
  string variable = match.Groups[tokenVar].Value;  // = "Else" 
}

在与一位同事谈论此事后,我被告知当我的模式使用增加并且我想使用名为 "Sprache" 的 C# 解析器构建库(它介于正则表达式和类似 ANTLR 的工具集之间)具有更好的可维护性。