【发布时间】:2018-03-13 12:51:50
【问题描述】:
我正在用 C# 编写一个小型标记器。
在 PCRE 正则表达式规范中有简洁的 MARK 关键字:
https://pcre.org/current/doc/html/pcre2syntax.html#SEC23
这就是它的工作原理:
<?php
$string = 'bar';
$matches = [];
preg_match('~(?|foo(*:1)
|bar(*:2)
|baz(*:3))~x', $string, $matches);
var_dump($matches);
//> array(2) {
//> [0]=> string(3) "bar"
//> ["MARK"]=> string(1) "2"
//> }
如您所见,结果集中的MARK 参数允许您查看正则表达式的哪个分支实际匹配。不幸的是,.NET 正则表达式框架不支持 MARK 关键字。这就是我现在正在做的事情:
var pattern = @"(
(?<foo>foo)
|(?<bar>bar)
|(?<baz>baz)
)";
var regexOptions = RegexOptions.ExplicitCapture | RegexOptions.IgnorePatternWhitespace;
var regex = new Regex(pattern, regexOptions);
var matches = regex.Matches("bar");
foreach (Match match in matches)
{
int? mark = null;
if (match.Groups["foo"].Success)
{
mark = 1;
}
else if (match.Groups["bar"].Success)
{
mark = 2;
}
else if (match.Groups["baz"].Success)
{
mark = 3;
}
}
基本上,我需要重构整个正则表达式以查看实际匹配的捕获组。
这似乎倒退了。有没有更好的方法可以做同样的事情?
我需要这个的原因是因为在标记器中我不仅需要知道语法是否有效,还需要知道匹配的标记实际上是哪种标记类型。
【问题讨论】:
-
命名捕获组怎么样?
-
将可能的标记放入字典并循环遍历它们。然后尝试在字符串的开头进行匹配,看看哪个匹配 - 在这里,获取令牌名称,使用字符串并打破循环。
-
如果您需要确定匹配的是哪个令牌,为什么不直接读取外部组的值?
-
@revo 我当前的解决方案确实使用命名捕获组;)
-
你能告诉我这个我可以将正确的令牌类型(它是一个枚举)传递给 MARK 值吗?我没听懂。