Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何提高.NET正则表达式的性能?_C#_Regex_Performance - Fatal编程技术网

C# 如何提高.NET正则表达式的性能?

C# 如何提高.NET正则表达式的性能?,c#,regex,performance,C#,Regex,Performance,我有一个正则表达式,它解析Razor模板语言的一个子集(非常小)。最近,我在regex中添加了更多的规则,这大大降低了它的执行速度。我想知道:是否有某些正则表达式构造已知是缓慢的?我正在使用的模式是否有一种重组,既能保持可读性又能提高性能?注意:我已确认此性能问题发生在编译后 以下是模式: new Regex( @" (?<escape> \@\@ )" + @"| (?<comment> \@\* ( ([^\*]\

我有一个正则表达式,它解析Razor模板语言的一个子集(非常小)。最近,我在regex中添加了更多的规则,这大大降低了它的执行速度。我想知道:是否有某些正则表达式构造已知是缓慢的?我正在使用的模式是否有一种重组,既能保持可读性又能提高性能?注意:我已确认此性能问题发生在编译后

以下是模式:

new Regex(
              @"  (?<escape> \@\@ )"
            + @"| (?<comment> \@\* ( ([^\*]\@) | (\*[^\@]) | . )* \*\@ )"
            + @"| (?<using> \@using \s+ (?<namespace> [\w\.]+ ) (\s*;)? )"

            // captures expressions of the form "foreach (var [var] in [expression]) { <text>" 
/* ---> */      + @"| (?<foreach> \@foreach \s* \( \s* var \s+ (?<var> \w+ ) \s+ in \s+ (?<expressionValue> [\w\.]+ ) \s* \) \s* \{ \s* <text> )"

            // captures expressions of the form "if ([expression]) { <text>" 
/* ---> */      + @"| (?<if> \@if \s* \( \s* (?<expressionValue> [\w\.]+ ) \s* \) \s* \{ \s* <text> )"  

            // captures the close of a razor text block
            + @"| (?<endBlock> </text> \s* \} )"

            // an expression of the form @([(int)] a.b.c)
            + @"| (?<parenAtExpression> \@\( \s* (?<castToInt> \(int\)\s* )? (?<expressionValue> [\w\.]+ ) \s* \) )"
            + @"| (?<atExpression> \@ (?<expressionValue> [\w\.]+ ) )"
/* ---> */      + @"| (?<literal> ([^\@<]+|[^\@]) )",
            RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline | RegexOptions.ExplicitCapture | RegexOptions.Compiled);
新正则表达式(
@"  (? \@\@ )"
+ @"| (? \@\* ( ([^\*]\@) | (\*[^\@]) | . )* \*\@ )"
+@“|(?\@使用\s+(?[\w\.]+)(\s*)?)
//捕获形式为“foreach(var[var]in[expression]){的表达式
/*-->*/++“|”(?\@foreach\s*\(\s*var\s+(?\w+)\s+in\s+(?[\w\.]+)\s*\{\s*)”
//捕获形式为“if([expression]){”的表达式
/*-->*/+@“|(?\@if\s*\(\s*(?[\w\.]+)\s*\)\s*\{\s*)”
//捕获razor文本块的结尾
+@“|”(?\s*\})”
//@([(int)]a.b.c)形式的表达式
+@“|”(?\@\(\s*(?\(int\)\s*)(?[\w\.]+)\s*)”
+@“|”(?\@(?[\w\.]+)”

/*-->*/+@“|”([^\由于您没有锚定表达式,引擎必须在字符串的每个位置检查每个备选子模式,然后才能确定它找不到匹配项。这总是很耗时,但如何才能使其不那么耗时

一些想法:

我不喜欢第二行中试图匹配注释的子模式,我认为它不会正常工作

我可以看到您正试图使用
(([^\*]\@)(\*[^\@])做什么。)*
-允许注释中包含
@
*
,只要它们前面没有
*
或后面没有
@
。但是由于组的
*
量词和第三个选项
,子模式将很高兴地匹配
*@
,因此将其他选项呈现红色永达

假设您试图匹配的Razor子集不允许多行注释,我建议使用第二行

+ @"| (?<comment> @\*.*?\*@ )"
+@“|(?@\*.*.\*@)”
i、 e.延迟匹配任何字符(但换行符),直到遇到第一个
*@
。 您正在使用
RegexOptions.ExplicitCapture
意味着只捕获命名的组,因此缺少
()
应该不是问题


我也不喜欢
([^\@因为你没有锚定表达式,引擎必须在字符串的每个位置检查每个备选子模式,然后才能确定它找不到匹配项。这总是很耗时,但怎么能让它不那么耗时呢

一些想法:

我不喜欢第二行中试图匹配注释的子模式,我认为它不会正常工作

我可以看到您正试图使用
(([^\*]\@)(\*[^\@])做什么。)*
-允许注释中包含
@
*
,只要它们前面没有
*
或后面没有
@
。但是由于组的
*
量词和第三个选项
,子模式将很高兴地匹配
*@
,因此将其他选项呈现红色永达

假设您试图匹配的Razor子集不允许多行注释,我建议使用第二行

+ @"| (?<comment> @\*.*?\*@ )"
+@“|(?@\*.*.\*@)”
i、 e.延迟匹配任何字符(但换行符),直到遇到第一个
*@
。 您正在使用
RegexOptions.ExplicitCapture
意味着只捕获命名的组,因此缺少
()
应该不是问题


我也不喜欢
([^\@正如其他人所提到的,您可以通过删除不必要的转义(例如转义
@
或在字符类中转义
\
之外的字符;例如,使用
[^*]
而不是
[^\*]
)来提高可读性

以下是一些提高性能的想法:

订购不同的备选方案,让最有可能的方案排在第一位。

正则表达式引擎将尝试按照每个选项在正则表达式中出现的顺序匹配它们。如果您将更可能的选项放在前面,那么对于大多数情况,引擎将不必浪费时间尝试匹配不太可能的选项

删除不必要的回溯

不是“使用”选项的结尾:
@“|”(?\@使用\s+(?[\w\.]+)(\s*)?)”

如果由于某种原因,您有大量的空白,但在using行末尾没有关闭
,则正则表达式引擎必须回溯每个空白字符,直到它最终确定它不能匹配
(\s*;)
。在您的情况下,
(\s*;)?
可以替换为
\s*;?
以防止在这些情况下出现回溯

此外,您可以使用原子组
(?>
来防止通过量词(例如
*
+
)进行回溯。这确实有助于在找不到匹配项时提高性能。例如,“foreach”选项包含
\s*(\s*
)如果您找到文本
foreach var.“
,“foreach”替代项将贪婪地匹配
foreach
之后的所有空格,然后在找不到开口
)时失败。然后它将回溯,每次一个空格字符,并尝试匹配
位于上一个位置,直到它确认它无法匹配该行。使用原子组
(?>\s*)\(
将导致正则表达式引擎