将找到的子字符串提取到变量的模式匹配
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 的工具集之间)具有更好的可维护性。
我有一些定义格式的字符串,例如 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
.
我手头没有代码,在我再次从头开始编码之前,我想我最好问问是否有人已经完成并发布了它。
解析表达式让我想起了 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 的工具集之间)具有更好的可维护性。