Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.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# C中的大字符串正则表达式替换性能#_C#_Regex_Performance_Replace - Fatal编程技术网

C# C中的大字符串正则表达式替换性能#

C# C中的大字符串正则表达式替换性能#,c#,regex,performance,replace,C#,Regex,Performance,Replace,我在C#中遇到了正则表达式性能问题 我需要替换一个非常大的字符串(270k字符,不问为什么…)。正则表达式匹配大约3k次 private static Regex emptyCSSRulesetRegex = new Regex(@"[^\};\{]+\{\s*\}", RegexOptions.Compiled | RegexOptions.Singleline); public string ReplaceEmptyCSSRulesets(string css) { return em

我在C#中遇到了正则表达式性能问题

我需要替换一个非常大的字符串(270k字符,不问为什么…)。正则表达式匹配大约3k次

private static Regex emptyCSSRulesetRegex = new Regex(@"[^\};\{]+\{\s*\}", RegexOptions.Compiled | RegexOptions.Singleline);

public string ReplaceEmptyCSSRulesets(string css) {
  return emptyCSSRulesetRegex.Replace(css, string.Empty);
}
传递给该方法的字符串如下所示:

.selector-with-statements{border:none;}.selector-without-statements{}.etc{}
目前,在C#中,替换过程需要1500ms,但当我在Javascript中执行完全相同的操作时,只需要100ms

我用于计时的Javascript代码:

console.time('reg replace');
myLargeString.replace(/[^\};\{]+\{\s*\}/g,'');
console.timeEnd('reg replace');
我还尝试通过以相反顺序循环匹配项并在StringBuilder中替换字符串来进行替换。那没用


在这种情况下,我对C#和Javascript之间的性能差异感到惊讶,我认为我做错了什么,但我想不出任何事情。

我无法真正解释Javascript和C#(*)之间的时间差异。但是您可以尝试改进模式的性能(这会产生大量回溯):

private static Regex emptyCSSRulesetRegex=new Regex(@“(?[^};{]+)(?:{\s*}(?)”,RegexOptions.Compiled);
公共字符串替换EmptyCSRuleSets(字符串css){
返回emptyCSSRulesetRegex.Replace(css,@“${keep}”);
}
原始模式的一个问题是,当花括号不为空(或没有填充空格)时,正则表达式引擎将继续在打开花括号之前测试每个位置(结果始终相同)。例如:使用字符串
abcd{1234}
您的模式将从
a
开始测试,然后从
b
开始测试

我建议的模式将消耗
abcd
,即使后面没有空的花括号,因此不会测试
bcd
的位置

abcd
在名为
keep
的组中捕获,但当找到空的花括号时,捕获组将被空的捕获组覆盖

您可以了解这两种模式所需的步骤数(请检查调试器):

注意:如果将
[^}{;]+
包含在一个原子组中,则可以改进原始模式。此更改会将所需的步数除以2(与原始模式相比),但即使如此,由于前面解释的原因,步数仍然很高


(*)javascript正则表达式引擎可能足够聪明,不会重试所有这些位置,但这只是一个假设。

我认为用于JS和C的正则表达式引擎是不同的。你不应该跨语言比较特性。我不确定C是否正确,但在Java中,正则表达式的创建(当你进行
匹配时)(
)它本身是一个耗时的过程。它涉及同步和其他耗时的内容。请尝试将
\s
更改为
[\f\n\r\t\v\u00A0\u2028\u2029]
或使用
RegexOptions.ECMAScript
。在JS和C#中处理字符类的方式上存在差异,我同意,但差异很大……因此这可能是一个信号,表明我在C#中做错了什么。我正试图找出确切的原因。看看@stribizev你认为正则表达式是问题所在吗?That与javascript正则表达式的执行时间不一致。但是我做了一个只匹配而不替换的测试,这在C#中很快。谢谢!您的正则表达式似乎可以工作。我将在javascript正则表达式中尝试also@WillemdeWit:您不能在javascript中使用相同的模式,因为它不支持命名捕获,但您可以编写一些东西使用回调函数作为替换类似:
str.replace(/[^};{]+({\s*})/g,函数(m,g1){return(g1)''':m;});
结果也比以前快了10倍。比以前快了10倍?或者比JS@CasimiretHippolyte中的前一个正则表达式快了10倍-你能带上“原始模式”和“新模式”吗答案中的正则表达式-外部链接不受欢迎,因为外部站点可能会更改,从而破坏SO社区的宝贵答案。除了在答案中显示正则表达式外,您当然可以拥有该链接。
private static Regex emptyCSSRulesetRegex = new Regex(@"(?<keep>[^};{]+)(?:{\s*}(?<keep>))?", RegexOptions.Compiled);

public string ReplaceEmptyCSSRulesets(string css) {
    return emptyCSSRulesetRegex.Replace(css, @"${keep}");
}