c#正则表达式速度问题

c#正则表达式速度问题,c#,regex,C#,Regex,我在C#中有一个正则表达式,其中模式是8000多个单词(或单词组),每个单词由单词边界分隔,即: "\\bword1\\b|\\bword2 word3 word4\\b|.......etc" 我试图将字符串中的一个单词(或一组单词)与此表达式中的任何单词(或一组单词)进行匹配。这一切都很好,除了我发现平均需要37毫秒才能完成操作 有趣的是,如果我做同样的事情,但使用String.IndexOf和一些复杂的方法,它确实运行得更快(但仍然太慢),我觉得这很奇怪 我知道其他正则表达式引擎,特别是

我在C#中有一个正则表达式,其中模式是8000多个单词(或单词组),每个单词由单词边界分隔,即:

"\\bword1\\b|\\bword2 word3 word4\\b|.......etc"
我试图将字符串中的一个单词(或一组单词)与此表达式中的任何单词(或一组单词)进行匹配。这一切都很好,除了我发现平均需要37毫秒才能完成操作

有趣的是,如果我做同样的事情,但使用
String.IndexOf
和一些复杂的方法,它确实运行得更快(但仍然太慢),我觉得这很奇怪

我知道其他正则表达式引擎,特别是re2/google,但我真的很想在可能的情况下使用C#内置功能


如果有人有建议,我们将不胜感激。

要理解正则表达式为何运行缓慢,您只需设想正则表达式是如何工作的

在您的情况下(8000个备选方案)

  • 第一步。从输入字符0开始
  • 第二步。尝试匹配备选方案0。哎呀,没有对手
  • 第三步。尝试匹配备选方案1。哎呀,没有对手
  • 步骤4000。尝试匹配备选方案4001。耶!第一个字符匹配
  • 步骤4001。尝试匹配备选方案4001。耶!第二个字符匹配
  • 步骤4002。尝试匹配备选方案4001。哎呀,没有对手
  • 步骤4003。尝试匹配备选方案4002。哎呀,没有对手
  • 步骤8963。尝试匹配备选方案7999。哎呀,没有对手
  • 步骤8964。输入字符0处的所有替代项均失败
  • 步骤8965。移动到输入字符1
  • 步骤8966。尝试匹配备选方案0。哎呀,没有对手
输入字符串越长,正则表达式的可选项越多,并且输入字符串中出现的“几乎,但不完全”匹配越多,速度就越慢

如果使用
String.IndexOf()
可以加快速度,那么就这样做。使用正则表达式,您将永远无法加快速度


探索搜索字符串中单词的其他方法。哪种方法对您有效很大程度上取决于您的输入是什么样子的。

要理解正则表达式速度慢的原因,您只需设想正则表达式是如何工作的

在您的情况下(8000个备选方案)

  • 第一步。从输入字符0开始
  • 第二步。尝试匹配备选方案0。哎呀,没有对手
  • 第三步。尝试匹配备选方案1。哎呀,没有对手
  • 步骤4000。尝试匹配备选方案4001。耶!第一个字符匹配
  • 步骤4001。尝试匹配备选方案4001。耶!第二个字符匹配
  • 步骤4002。尝试匹配备选方案4001。哎呀,没有对手
  • 步骤4003。尝试匹配备选方案4002。哎呀,没有对手
  • 步骤8963。尝试匹配备选方案7999。哎呀,没有对手
  • 步骤8964。输入字符0处的所有替代项均失败
  • 步骤8965。移动到输入字符1
  • 步骤8966。尝试匹配备选方案0。哎呀,没有对手
输入字符串越长,正则表达式的可选项越多,并且输入字符串中出现的“几乎,但不完全”匹配越多,速度就越慢

如果使用
String.IndexOf()
可以加快速度,那么就这样做。使用正则表达式,您将永远无法加快速度


探索搜索字符串中单词的其他方法。哪一个对你有效很大程度上取决于你的输入看起来如何。

我建议切换到,因为它似乎更适合你的任务

以下是您可以做的事情的草稿:

// produce string[] containing your words
var words = myRegexp.split("\\b|\\");

var mySet = new HashSet<string>(words);
// usage
mySet.Contains("find this");
//生成包含单词的字符串[]
var words=myRegexp.split(\\b| \\”;
var mySet=新哈希集(单词);
//用法
mySet.Contains(“查找此”);

我建议切换到,因为它似乎更适合您的任务

以下是您可以做的事情的草稿:

// produce string[] containing your words
var words = myRegexp.split("\\b|\\");

var mySet = new HashSet<string>(words);
// usage
mySet.Contains("find this");
//生成包含单词的字符串[]
var words=myRegexp.split(\\b| \\”;
var mySet=新哈希集(单词);
//用法
mySet.Contains(“查找此”);

这些\b在现实生活中有两条斜线。。。他们刚发帖就逃走了!您是否使用了RegexOptions.Compiled?我想Tohugh 8000+字模式太过分了。@james这就是为什么编辑器中有一个“格式为代码”选项的原因。;)您是否在RegexOptions中使用了compile选项?要在构造函数中使用,var regex=new regex(string,RegexOptions)这是regexp的一个非常奇怪的用法,为什么不将regexp转换为字符串数组/字典并使用收集方法来搜索那些在现实生活中有两个斜杠的\b。。。他们刚发帖就逃走了!您是否使用了RegexOptions.Compiled?我想Tohugh 8000+字模式太过分了。@james这就是为什么编辑器中有一个“格式为代码”选项的原因。;)您是否在RegexOptions中使用了compile选项?要在构造函数中使用,var regex=new regex(string,RegexOptions)这是regexp的一个非常奇怪的用法,为什么不将regexp转换为字符串数组/字典并使用集合方法进行搜索谢谢,我将继续尝试找到方法。。。显然,一种方法是减少正则表达式中的字数,但我目前正在努力做到这一点(长话短说),我认为正则表达式不再是一种值得遵循的策略。相信这也可以称为“灾难性回溯”不,这不是灾难性回溯。这个表达式以最佳速度运行,只是在这个用例中最佳速度并不是很快。谢谢,我会继续努力寻找方法。。。显然,一种方法是减少正则表达式中的字数,但我目前正在努力做到这一点(长话短说),我认为正则表达式不再是一种值得遵循的策略。相信这也可以称为“灾难性回溯”不,这不是灾难性回溯。这个表达式以最佳速度运行,只是在这个用例中最佳速度并不是很快。