【问题标题】:Fastest way of processing regexp处理正则表达式的最快方法
【发布时间】:2012-09-13 21:44:46
【问题描述】:

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

谢谢

【问题讨论】:

  • 定义“慢慢地”。你确定它是正则表达式吗?文件系统、网络,还有其他什么是整体的一部分?每个时间单位处理多少行?我并不是说这不是您的(复杂)正则表达式,但您可能想确保这是您的问题。
  • 另外,对于括号内的 python 字符串,+ 连接是多余的。 Python 会自动连接这些字符串。
  • if len(line) == 0: 可以缩短为if len(line): 可以缩短为if line: 不能再缩短了。
  • .* 事情可能会导致很多回溯,尝试摆脱它们(替换为[^...])。您还可以发布您输入的示例吗?
  • grep/awk 是正则表达式的速度参考:stackoverflow.com/a/11192394/718618

标签: python regex perl bash sed


【解决方案1】:

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

line.split()      #Split based on whitespace

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

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

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

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

【讨论】:

    【解决方案2】:

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

    1. 将输入文件分成块(例如,FileLen/NumProcessors 字节 每个)。
    2. 将每个块的开头和结尾调整为 \n,这样您就可以使用整行 每个工人。
    3. fork() 创建 NumProcessors 工作程序,每个工作程序都读取自己的
      字节范围从文件并写入他自己的输出文件。
    4. 根据需要合并输出文件。

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

    【讨论】:

    • 这增加了一整层的复杂性并且依赖于平台。我只会将此作为最后的手段。
    • “复杂层”在这种情况下大约是 30-40 行代码,以便宜的方式获得 8 倍的加速。
    【解决方案3】:

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

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

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

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

    【讨论】:

    • 正在使用预编译的正则表达式。但这可能并不重要,因为 Python 会自动缓存正则表达式,就像 Perl 一样。这里的问题是正则表达式本身,很可能是 .* 的 @thg435 mentioned
    猜你喜欢
    • 1970-01-01
    • 2022-01-22
    • 2020-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-29
    • 2011-09-14
    • 1970-01-01
    相关资源
    最近更新 更多