在.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
Run Code Online (Sandbox Code Playgroud)
我的字符串: 3 tbsp 1/2 tsp
结果组和捕获:
[测量] [0] = 3汤匙
[测量] [ 1 ] = 1/2茶匙
[整数] [0] = 3
[numtor] [ 0 ] = 1
[dentor] [ 0 ] = 2
[unit] [0] = tbsp
[unit] [ 1 ] = tsp
请注意,即使1/2 tsp在第二次捕获中,它的部分也在,[0]因为这些斑点以前未使用过.
有没有办法让所有部分都具有可预测的有用索引,而无需再次通过正则表达式重新运行每个组?
有没有什么方法可以让所有部分都具有可预测的有用索引,而不必再次通过正则表达式重新运行每个组?
不适用于捕获。如果您无论如何都要执行多个匹配,我建议您删除+并分别匹配测量的每个组件,如下所示:
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("");
}
Run Code Online (Sandbox Code Playgroud)
输出:
[measurement] = 3 tbsp
[integer] = 3
[unit] = tbsp
[measurement] = 1/2 tsp
[numtor] = 1
[dentor] = 2
[unit] = tsp
Run Code Online (Sandbox Code Playgroud)
开头的at\G确保匹配仅发生在上一个匹配结束的位置(或者如果这是第一次匹配尝试,则发生在输入的开头)。您还可以保存调用之间的匹配结束位置,然后使用双参数Matches方法在同一点恢复解析(就好像那确实是输入的开始)。