在.NET中,正则表达式并没有像我期望的那样组织捕获。 (我不会称这是一个错误,因为显然有人打算这样做。但是,我不希望它如何工作,也不会发现它有用。)
这个正则表达式用于配方成分(为了举例简化):
(?<measurement> # begin group
\s* # optional beginning space or group separator
(
(?<integer>\d+)| # integer
(
(?<numtor>\d+) # numerator
/
(?<dentor>[1-9]\d*) # denominator. 0 not allowed
)
)
\s(?<unit>[a-zA-Z]+)
)+ # end group. can have multiple
我的字符串:3 tbsp 1/2 tsp
结果组和捕获:
[测量] [0] = 3汤匙 [测量] [ 1 ] = 1/2茶匙
[整数] [0] = 3
[numtor] [ 0 ] = 1
[dentor] [ 0 ] = 2
[单位] [0] =汤匙
[单位] [ 1 ] = TSP
请注意,即使1/2 tsp
在第二次捕获中,它的部分位于[0]
,因为这些斑点以前未使用过。
有没有办法让所有部分都具有可预测的有用索引,而无需再次通过正则表达式重新运行每个组?
答案 0 :(得分:1)
好像你可能需要循环输入,一次匹配一个测量。然后,在该测量的循环迭代期间,您将可以预测访问该测量的各个部分。
答案 1 :(得分:1)
有没有办法让所有部分都具有可预测的有用索引,而无需再次通过正则表达式重新运行每个组?
没有捕获。如果您要进行多个匹配,我建议您删除+
并分别匹配度量的每个组成部分,如下所示:
string s = @"3 tbsp 1/2 tsp";
Regex r = new Regex(@"\G\s* # anchor to end of previous match
(?<measurement> # begin group
(
(?<integer>\d+) # integer
|
(
(?<numtor>\d+) # numerator
/
(?<dentor>[1-9]\d*) # denominator. 0 not allowed
)
)
\s+(?<unit>[a-zA-Z]+)
) # end group.
", RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture);
foreach (Match m in r.Matches(s))
{
for (int i = 1; i < m.Groups.Count; i++)
{
Group g = m.Groups[i];
if (g.Success)
{
Console.WriteLine("[{0}] = {1}", r.GroupNameFromNumber(i), g.Value);
}
}
Console.WriteLine("");
}
输出:
[measurement] = 3 tbsp
[integer] = 3
[unit] = tbsp
[measurement] = 1/2 tsp
[numtor] = 1
[dentor] = 2
[unit] = tsp
开头的\G
确保匹配仅在前一个匹配结束时发生(或者如果这是第一次匹配尝试则在输入的开头)。您还可以在调用之间保存匹配结束位置,然后使用双参数Matches
方法在同一点继续解析(就好像这实际上是输入的开始)。
答案 2 :(得分:-1)
看看这个....这里有一些可能有助于改进正则表达式的建议
(?<measurement> # begin group
\s* # optional beginning space or group separator
(
(?<integer>\d+)\.?| # integer
(
(?<numtor>\d+) # numerator
/
(?<dentor>[1-9]\d*) # denominator. 0 not allowed
)
)
\s(?<unit>[a-zA-Z]+)
)+ # end group. can have multiple
(?<integer>\d+)
我会尝试使用\s?
代替\.
来捕获空白区域,因为它正在逃离全站,并期望在某个地方出现一个句号。\/