如何提高这个正则表达式的性能?

时间:2015-09-02 06:16:41

标签: python regex

考虑正则表达式

^(?:\s*(?:[\%\#].*)?\n)*\s*function\s

旨在匹配以函数定义开头的Octave / MATLAB脚本文件。

但是,这个正则表达式的性能非常慢,而且我不完全确定原因。例如,如果我尝试用Python评估它,

>>> import re, time
>>> r = re.compile(r"^(?:\s*(?:[\%\#].*)?\n)*\s*function\s")
>>> t0=time.time(); r.match("\n"*15); print(time.time()-t0)
0.0178489685059
>>> t0=time.time(); r.match("\n"*20); print(time.time()-t0)
0.532235860825
>>> t0=time.time(); r.match("\n"*25); print(time.time()-t0)
17.1298530102

在英语中,最后一行是说我的正则表达式需要17秒来评估一个包含25个换行符的简单字符串!

我的正则表达式是什么让它变得如此缓慢,我该怎么做才能解决它?

编辑:为了澄清,我希望我的正则表达式匹配以下包含注释的字符串:

# Hello world
function abc

包括任何数量的空格,但不包括

x = 10
function abc

因为那时字符串不以“function”开头。请注意,注释可以以“%”或“#”开头。

2 个答案:

答案 0 :(得分:2)

\s替换为[\t\f ],以便他们不会抓住换行符。这应该只由整个非捕获组(?:[\t\f ]*(?:[\%\#].*)?\n)完成 问题是你有三个贪婪的消费者都匹配'\n'\s*(...\n)*\s*}。
在上一个时间示例中,他们会尝试组成a或任何子字符串{{1}的所有字符串bc25*'\n'(每个消费者一个)它首先是,d是被忽略的,然后是e 现在找到d+e == 25*'\n'abc的所有组合,以便e同时考虑一个或多个变量的空字符串。我现在做数学的时间已经太晚了,但我打赌这个数字很大:D

顺便说一下,regex101是一个很棒的网站,可以试用正则表达式。它们会自动分解表达式并解释它们的部分,甚至还提供调试器。

答案 1 :(得分:0)

要加速,你可以使用这个正则表达式:

public static void main(String args[]){
    Scanner scanner =  new Scanner(System.in);

    for (int i=0;i<2;i++){
       String string = scanner.next();
       int num = scanner.nextInt();


       System.out.printf("%-14s %03d %n", string, num);       //note the use of printf
       // %-14s  fifteen characters left-justified o to 14
       // %03d padded with leading zero

    }
}

由于您实际上并未实际捕获以p = re.compile(r"^\s*function\s", re.MULTILINE) #开头的行,因此您可以使用%模式并从MULTILINE关键字所在的同一行开始匹配找到。