为什么此正则表达式更快?

时间:2020-03-05 18:38:22  来源:igfitidea点击:

我正在用Cand编写某种Telnet客户端,我必须解析的是ANSI / VT100转义序列,尤其是那些用于颜色和格式设置的转义序列(此处有详细信息)。

我拥有的一种方法是找到所有代码并将其删除,因此,如果需要,我可以在不进行任何格式设置的情况下呈现文本:

public static string StripStringFormating(string formattedString)
{
    if (rTest.IsMatch(formattedString))
        return rTest.Replace(formattedString, string.Empty);
    else
        return formattedString;
}

我是正则表达式的新手,建议我使用此函数:

static Regex rText = new Regex(@"\e\[[\d;]+m", RegexOptions.Compiled);

但是,如果由于服务器上的错误导致转义代码不完整,则此操作将失败。因此,有人提出了这个建议,但我的朋友警告说,它可能会更慢(这也与我稍后可能遇到的另一种情况(z)相匹配):

static Regex rTest = 
              new Regex(@"(\e(\[([\d;]*[mz]?))?)?", RegexOptions.Compiled);

这不仅有效,而且实际上更快并且减少了对我的文本呈现的影响。有人可以向正则表达式新手解释,为什么呢? :)

解决方案

回答

如果不做详细分析,我想这是因为问号会更快。这些使正则表达式变得"懒惰",并在它们足以匹配时立即停止,而不是检查其余输入是否匹配。

我对这个答案并不完全满意,因为这主要适用于*或者+之后的问号。如果我对输入内容更加熟悉,那么对我来说可能更有意义。

(此外,对于代码格式设置,我们可以选择所有代码,然后按Ctrl + K使其添加所需的四个空格。)

回答

#1变慢的原因是[\ d;] +是贪婪的量词。使用+吗?或者 *?将要进行懒惰的量化。有关更多信息,请参见MSDN量词。

我们可能要尝试:

"(\e\[(\d{1,2};)*?[mz]?)?"

那对我们来说可能更快。

回答

我们真的要执行两次regexp吗?如果没有检查(对我不好),我会认为这会很好地工作:

public static string StripStringFormating(string formattedString)
{    
    return rTest.Replace(formattedString, string.Empty);
}

如果是这样,我们应该会看到它以两倍快的速度运行...

回答

我不确定这是否对工作有所帮助,但是很久以前,我写了一个正则表达式来解析ANSI图形文件。

(?s)(?:\e\[(?:(\d+);?)*([A-Za-z])(.*?))(?=\e\[|\z)

它将返回每个代码和与之关联的文本。

输入字符串:

<ESC>[1;32mThis is bright green.<ESC>[0m This is the default color.

结果:

[ [1, 32], m, This is bright green.]
[0, m, This is the default color.]