C# 使用Regex高效解析/lex令牌

C# 使用Regex高效解析/lex令牌,c#,.net,regex,vb.net,performance,C#,.net,Regex,Vb.net,Performance,我试图找到一种方法,在.NET中使用正则表达式来有效地确定字符串匹配的几种模式中的哪一种。如果我的标记是固定文本的,我会使用字典并简单地查找它们。然而,令牌中可以嵌入一个或多个数字序列以表示索引。我有几十到100个这样的代币。举个小例子,我想匹配以下令牌之一: ORDERID PRICE(\d+) QUANTITY(\d+) DESCRIPTION(\d+) WEIGHT(\d+)_(\d+) (想象中的用例是,我有一组名称-值对,名称使用嵌入的整数来允许重复。在本例中,想象一个有多行的订单,

我试图找到一种方法,在.NET中使用正则表达式来有效地确定字符串匹配的几种模式中的哪一种。如果我的标记是固定文本的,我会使用字典并简单地查找它们。然而,令牌中可以嵌入一个或多个数字序列以表示索引。我有几十到100个这样的代币。举个小例子,我想匹配以下令牌之一:

ORDERID
PRICE(\d+)
QUANTITY(\d+)
DESCRIPTION(\d+)
WEIGHT(\d+)_(\d+)
(想象中的用例是,我有一组名称-值对,名称使用嵌入的整数来允许重复。在本例中,想象一个有多行的订单,价格是第n行的价格。重量是第n行的第m个单独对象的重量(想象lineitem是某种套件))

请注意,这些令牌的组成超出了我的控制范围

我可以有效地识别这些标记,比如

^(?<oid>ORDERID)|(?<prc>PRICE(\d+))|(?<qty>QUANTITY(\d+)|(?<dsc>DESCRIPTION(\d+)|(?<wght>WEIGHT(\d+)_(\d+)$
不幸的是,据我所知,要确定哪个令牌与Regex.Match对象匹配,我必须遍历所有可能的情况:

m.Groups["oid"].Success
m.Groups["prc"].Success
m.Groups["qty"].Success
m.Groups["dsc"].Success
m.Groups["wght"].Success
随着令牌数量的增加,成本呈线性增长(或者更可能是n log n)。比如说,如果有一个SuccessGroups集合,我可以遍历它,它通常(在我的用法中)只有一个元素:匹配的特定组

我可以编写自己的解析算法,创建一个trie或类似的数据结构,但我不愿意重新实现一些Regex已经实现的东西,但似乎不能让我有效地访问


有什么想法或建议吗?

可能使用组,它会记录第一个匹配的,您可以迭代匹配,而不是标记

正则表达式中可能匹配的每个组都有一个组。在我们识别的标记数量上,迭代组是线性的。正则表达式引擎已经识别了匹配的令牌,我只想有效地提取这些信息。与执行正则表达式迭代组列表的成本相比,这应该是毫无意义的,对吗?你的基准测试显示了什么?不对。匹配一个预编译的正则表达式实际上是非常有效的:它是一个确定性有限状态自动机,其执行与匹配的输入字符串长度近似线性(如果您希望降低空间效率,则可以严格采用线性结构,但您通常会使用更节省空间的结构来确定给定输入字符的下一个状态,该结构在可能的下一个字符数上可以是线性的,在下一个字符数上可以是对数n).我用我需要识别的80ish标记做了一个简单的测试。我只做了匹配,然后我做了匹配,然后通过迭代组找到成功的标记。迭代组的成本大约等于实际识别的成本,也就是说,加起来是两倍长。我发现一个m平均而言,修补需要约3.6个小时,搜索结果需要约7.5个小时。我看不出任何可用的API可以实现这一点。它没有在组类上公开组名,这非常糟糕。这将解决您的问题,因为组是按捕获顺序返回的。
m.Groups["oid"].Success
m.Groups["prc"].Success
m.Groups["qty"].Success
m.Groups["dsc"].Success
m.Groups["wght"].Success