【问题标题】:best way to extract data using re.compiler使用 re.compiler 提取数据的最佳方法
【发布时间】:2017-02-05 13:06:40
【问题描述】:

我需要从不同的文本文件中提取(大量)信息。 我想知道是否有比以下更短更有效的方法:

第一部分:(N行)

N1 = re.compile(r'')
N2 = re.compile(r'')
.
Nn = re.compile(r'')

第二部分:(2N 行)

with open(filename) as f:
  for line in f:
    if N1.match(line):
      var1 = N1.match(line).group(x).strip()
    elif N2.match(line):
      var2 = N1.match(line).group(x).strip()
    elif Nn.match(line):
      varn = Nn

您是否建议将 re.compile 变量(第 1 部分)与第 2 部分分开。在这种情况下,你们使用什么?也许是一个将正则表达式作为参数传递的函数?并且每次都调用它。

在我的例子中,N 是 30,这意味着我有 90 行来提供字典,但逻辑很少,或者根本没有逻辑。

【问题讨论】:

  • 一般来说,如果你想要n的东西,使用list
  • 提取出来的数据会存储在列表和字典中,但是为什么要在提取之前使用列表呢?
  • ...因为您想要的东西比定义 n 用单独名称编译的正则表达式更短、更高效?
  • 他的意思是可能使用类似 [re.compile(r''), re.compile(r''), re.compile(r'')] 而不是 N1 N2 N3然后你可以在 f: for r in regexes 中做 for lines
  • 你能不能让你的问题更具体一点,不那么笼统?当不清楚(a)你想要匹配什么样的东西,(b)正则表达式有何不同,(c)你要对匹配做什么,(d)分开的目的是什么时,真的很难提出任何建议变量服务,(e)以及为什么这些表达式显然是另一个表达式所独有的(因为您只使用elifs)。

标签: python regex data-extraction


【解决方案1】:

我将尝试回答这个问题,而无需真正知道您在 实际上 在那里做什么。所以这个答案可能对你有帮助,也可能没有。

首先re.compile做的是预编译一个正则表达式,这样以后可以用,不用每次用都编译。当您有一个在整个程序中多次使用的正则表达式时,这主要是有用的。但是,如果表达式只使用了几次,那么预先编译它并没有太大的好处。

因此,您应该问问自己,尝试匹配所有这些表达式的代码运行频率是多少。在脚本执行期间是否只有一次?然后,您可以通过内联表达式来简化代码。由于您正在为文件中的每一行运行匹配项,因此预编译在这里可能是有意义的。

但是仅仅因为您预编译了表达式,这并不意味着您应该马虎并经常匹配相同的表达式。看这段代码:

if N1.match(line):
    var1 = N1.match(line).group(x).strip()

假设有一个匹配,这将运行N1.match() 两次。这是您应该避免的开销,因为匹配表达式可能相对昂贵(取决于表达式),即使表达式已经预编译。

相反,只需匹配一次,然后重复使用结果:

n1_match = N1.match(line)
if n1_match:
    var1 = n1_match.group(x).strip()

查看您的代码,您的正则表达式似乎也是互斥的——或者至少您只使用第一个匹配项并跳过其余的匹配项。在这种情况下,您应该确保订购支票 以便首先完成最常见的检查。这样,您就可以避免运行太多无论如何都不匹配的表达式。此外,请尝试对它们进行排序,以减少运行更复杂的表达式的频率。

最后,您将在单独的变量varN 中收集匹配结果。在这一点上,我质疑你到底在做什么,因为在你所有的 if 检查之后,你没有一个明确的方法来确定结果是什么以及使用哪个变量。此时,将其收集在单个变量中或在条件主体中移动特定逻辑可能更有意义。但是你提供的信息量很难说清楚。

【讨论】:

  • 大多数预编译的 RE 会在每个文件中使用一次(或两次),但脚本每天会运行一百个文件。是的。它们是互斥的,如果它们匹配一条线,我 100% 确定该线不会有任何其他信息。我知道文件结构,所以如果我知道最后一行总是有我需要的数据,我把 re.match 放在最后。在 for 结束时,每个 var 将提供 3 个 dicts。出于这个原因,我在那里有那些变量。主字典将由或多或少的 110 个文件提供。我真的不知道这是否是从或多或少的结构化文本/日志中获取数据的最佳方式
  • 如果脚本运行多次,但运行它的 Python 进程在其间终止,那么预编译表达式将无济于事。
【解决方案2】:

正如re module documentation 中提到的,您通过re 方法传递的正则表达式被缓存:根据您拥有的表达式数量,自己缓存它们可能没有用。

话虽如此,你应该列出你的正则表达式,这样一个简单的 for 循环就可以让你测试你的所有模式。

regexes = map(re.compile, ['', '', '', '', ...])
vars = ['']*len(regexes)
with open(filename) as f:
  for line in f:
    for i,regex in enumerate(regexes):
      if regex.match(line):
         var[i] = regex.match(line).group(x).strip()
         break  # break here if you only want the first match for any given line.

【讨论】:

  • 请注意,OP 的代码在第一次匹配时停止,而您的循环将始终匹配所有表达式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-16
  • 2016-08-03
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
相关资源
最近更新 更多