处理正则表达式的最快方法

时间:2012-09-21 12:55:54

标签: python regex perl bash sed

我在python中有一个脚本来处理一个日志文件 - 它解析这些值并简单地用tab加入它们。

p = re.compile(
    "([0-9/]+) ([0-9]+):([0-9]+):([0-9]+) I.*"+
    "worker\\(([0-9]+)\\)(?:@([^]]*))?.*\\[([0-9]+)\\] "+
    "=RES= PS:([0-9]+) DW:([0-9]+) RT:([0-9]+) PRT:([0-9]+) IP:([^ ]*) "+
    "JOB:([^!]+)!([0-9]+) CS:([\\.0-9]+) CONV:([^ ]*) URL:[^ ]+ KEY:([^/]+)([^ ]*)"
  )

for line in sys.stdin:
  line = line.strip()
  if len(line) == 0: continue
  result = p.match(line)
      if result != None:
    print "\t".join([x if x is not None else "." for x in result.groups()])

但是,脚本的运行速度非常慢,处理数据需要很长时间。

如何以更快的方式实现相同的行为?的Perl / SED / PHP /击/...?

由于

3 个答案:

答案 0 :(得分:2)

如果没有看到您的输入,很难知道,但看起来您的日志文件由空格分隔的字段组成,并且内部不包含任何空格。如果是这样,您可以首先拆分空白以将各个日志字段放入数组中。即

line.split()      #Split based on whitespace

line.split(' ')   #Split based on a single space character

之后,使用一些小的正则表达式甚至简单的字符串操作从您想要的字段中提取数据。

它可能会更有效率,因为大部分线处理都是通过简单的规则完成的。你不会有潜在的回溯陷阱,你会有更多可读代码,不太可能包含错误。

我不了解Python,所以我无法写出完整的代码示例,但这是我在Perl中采用的方法。

答案 1 :(得分:1)

我正在编写Perl,而不是Python,但最近我使用这种技术来解析非常大的日志:

  1. 将输入文件分割为块(例如,FileLen / NumProcessors字节 每个)。
  2. 将每个块的开始和结束调整为\ n,这样您就可以使用全行 每个工人。
  3. fork()创建NumProcessors工作者,每个工作者都读取自己的工作 bytes来自文件并写入自己的输出文件。
  4. 根据需要合并输出文件。
  5. 当然,你也应该努力优化正则表达式,例如减少使用。* cus它会产生许多回溯,这很慢。但无论如何,99%你会通过这个regexp在CPU上遇到瓶颈,所以在8个CPU上工作应该会有所帮助。

答案 2 :(得分:1)

在Perl中,可以使用预编译的regexp,如果你多次使用它们会快得多。

http://perldoc.perl.org/perlretut.html#Compiling-and-saving-regular-expressions

“qr //运算符出现在perl 5.005中。它编译正则表达式,但不适用它。”

如果数据很大,那么通过将数据拆分成片段来处理它是合法的。 CPAN中有几个模块可以使这更容易。