C# 防止正则表达式中的重复匹配

C# 防止正则表达式中的重复匹配,c#,regex,unique,distinct,C#,Regex,Unique,Distinct,下面的代码 string expression = "(\\{[0-9]+\\})"; RegexOptions options = ((RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline) | RegexOptions.IgnoreCase); Regex tokenParser = new Regex(expression, options); MatchCollection matches = tokenParser

下面的代码

string expression = "(\\{[0-9]+\\})";
RegexOptions options = ((RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline) | RegexOptions.IgnoreCase);
Regex tokenParser = new Regex(expression, options);

MatchCollection matches = tokenParser.Matches("The {0} is a {1} and the {2} is also a {1}");
将匹配并捕获“{0}”、“{1}”、“{2}”和“{1}”


是否可以更改它(正则表达式或正则表达式的选项),以便它匹配并捕获“{0}”、“{1}”和“{2}”。换句话说,如果您只想更改一个实例,则每个匹配只应捕获一次

string expression = "(\\{[0-9]+\\})"; \\one or more repetitions 


正则表达式可以解决很多问题,但不是每个问题。使用工具箱中的其他工具如何

var parameters = new HashSet<string>(
    matches.Select(mm => mm.Value).Skip(1));

这是我想到的

private static bool TokensMatch(string t1, string t2)
{
  return TokenString(t1) == TokenString(t2);
}

private static string TokenString(string input)
{
  Regex tokenParser = new Regex(@"(\{[0-9]+\})|(\[.*?\])");

  string[] tokens = tokenParser.Matches(input).Cast<Match>()
      .Select(m => m.Value).Distinct().OrderBy(s => s).ToArray<string>();

  return String.Join(String.Empty, tokens);
}
专用静态布尔令牌匹配(字符串t1、字符串t2)
{
返回TokenString(t1)=TokenString(t2);
}
私有静态字符串令牌字符串(字符串输入)
{
Regex-tokenParser=new-Regex(@“(\{[0-9]+\})\[*?\]);
string[]tokens=tokenParser.Matches(input.Cast())
.Select(m=>m.Value).Distinct().OrderBy(s=>s.ToArray();
返回String.Join(String.Empty,tokens);
}

请注意,正则表达式与我问题中的正则表达式之间的差异是由于我考虑了两种类型的令牌;编号的由{}分隔,命名的由[]分隔

这里有一些东西可以用于纯正则表达式解决方案:

Regex r = new Regex(@"(\{[0-9]+\}|\[[^\[\]]+\])(?<!\1.*\1)",
                    RegexOptions.Singleline);

Regex r=new Regex(@“(\{[0-9]+\}\\[^\[\]]+\]))(?我有点困惑,看起来您是在用String.Format(“This{0}和This{1}”,“Hello”,“World”)描述已经可用的功能。如果没有,则可以提供输入和输出的实际具体示例?简单地说,当运行正则表达式捕获给定字符串时,我是否可以防止它捕获输入中包含的该字符串的重复实例。与string.Format无关,只是包含令牌的字符串稍后将在string.Format.If中使用put是“…{0}…{1}…{0}…{1}”如何使捕获集合为{0},{1}而不是{0},{1},{0},{1},换句话说。不起作用。令牌{10},{11}等将不再匹配,{0},{1}到{9}的多个实例仍然会被捕获(如果它们存在)。此外,您只想匹配一个数字,{1}计数说明符是多余的。Meta comment,第0个匹配项是整个匹配语料库。我正在考虑类似的方法,以便在正则表达式完成其工作后使匹配项唯一。只是想知道正则表达式本身是否有一些魔力,可以在无需额外代码的情况下自行完成此操作。请参阅我提出的解决方案的答案。有时,您可以告诉你你想要什么样的正则表达式,但通常是以可读性或性能为代价的。我倾向于选择简单的方法,看看我是否需要更多的正则表达式:-DRegexOptions.Compiled可能有助于将正则表达式移出方法并使其成为静态。谢谢Alan。我将继续使用我当前的解决方案,但扩展我对正则表达式的了解是很好的表达式。在正则表达式之外执行差异检查也更快。通过更改表达式并删除distinct()调用进行测试。返回相同的结果,但花费的时间几乎是原来的两倍。这是一个很好的提醒,过度使用正则表达式或任何工具可能并不总是最好的解决方案。
private static bool TokensMatch(string t1, string t2)
{
  return TokenString(t1) == TokenString(t2);
}

private static string TokenString(string input)
{
  Regex tokenParser = new Regex(@"(\{[0-9]+\})|(\[.*?\])");

  string[] tokens = tokenParser.Matches(input).Cast<Match>()
      .Select(m => m.Value).Distinct().OrderBy(s => s).ToArray<string>();

  return String.Join(String.Empty, tokens);
}
Regex r = new Regex(@"(\{[0-9]+\}|\[[^\[\]]+\])(?<!\1.*\1)",
                    RegexOptions.Singleline);