0

我在 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/Bash/...?

谢谢

4

3 回答 3

2

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

line.split()      #Split based on whitespace

或者

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

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

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

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

于 2012-09-21T13:48:11.287 回答
1

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

  1. 将输入文件划分为多个块(例如,每个 FileLen/NumProcessors 字节)。
  2. 将每个块的开始和结束调整为 \n,这样你就可以为每个工人采取完整的行。
  3. fork() 创建 NumProcessors 工作人员,每个工作人员
    从文件中读取自己的字节范围并写入自己的输出文件。
  4. 如果需要,合并输出文件。

当然,你也应该努力优化正则表达式,例如少用 .* ,因为它会创建很多回溯,这很慢。但无论如何,这个正则表达式 99% 的 CPU 都会遇到瓶颈,所以在 8 个 CPU 上工作应该会有所帮助。

于 2012-09-21T13:59:21.617 回答
1

在 Perl 中,可以使用预编译的正则表达式,如果您多次使用它们会更快。

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

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

如果数据很大,那么值得通过将数据拆分为多个片段来并行处理它。CPAN 中有几个模块使这更容易。

于 2012-09-21T15:28:54.720 回答