【问题标题】:Read a text file line by line and store variables on matching specific pattern in Python逐行读取文本文件并在 Python 中存储匹配特定模式的变量
【发布时间】:2018-08-29 19:33:23
【问题描述】:

我们有一个包含以下两行的大型日志文件:

00 LOG     |   Cycles Run:  120001
00 LOG     ! Virtual: Max> ?????????? bytes (?.???? gb), Current> 640733184 bytes (?.???? gb).

00 LOG     ! Virtual: Max> 1082470400 bytes (?.???? gb), Current> ????????? bytes (?.???? gb).

00 LOG     ! Actual: Max> ????????? bytes (?.???? gb), Current> 472154112 bytes (?.???? gb).

00 LOG     ! Actual: Max> 861736960 bytes (?.???? gb), Current> ????????? bytes (?.???? gb).

由于日志文件很大,我们希望逐行读取(而不是一次读取缓冲区中的整个文本),匹配特定的模式集并在单独的变量中选择值。

例如

00 LOG     |   Cycles Run:  120001

我们想要选择120001 并存储在一个变量中,比如cycle

另一方面,我们解析这些行:

00 LOG     ! Virtual: Max> ?????????? bytes (?.???? gb), Current> 640733184 bytes (?.???? gb).

00 LOG     ! Virtual: Max> 1082470400 bytes (?.???? gb), Current> ????????? bytes (?.???? gb).

00 LOG     ! Actual: Max> ????????? bytes (?.???? gb), Current> 472154112 bytes (?.???? gb).

00 LOG     ! Actual: Max> 861736960 bytes (?.???? gb), Current> ????????? bytes (?.???? gb).

标有? 的字符可以是任何数字。

我们想存储如下变量:

640733184 in var virtual_cur

1082470400 in var virtual_max

472154112 in var actual_cur

861736960 in var actual_max

Python 3.6 中写了一个 sn-p,但它打印的是空列表:

import re

filename = "test.txt"
with open(filename) as fp:  
   line = fp.readline()
   while line:
       cycle_num = re.findall(r'00 LOG     |   Cycles Run:  (.*?)',line,re.DOTALL)
       line = fp.readline()

print (cycle_num[0])

注意:我想选择单独变量中的每个值并使用它 稍后的。需要一个一个设置5个模式,匹配就取值 任何特定的模式,并将其放在无关变量中。

不确定第二个模式的通配符匹配。

请给我们建议一种有效的方法。

【问题讨论】:

  • 你想要两个变量,每个值一个吗?
  • 是的。对于第二个变量,我不确定如何使用带通配符的模式匹配来完成它。所以,没有把它包含在sn-p中。
  • 请注意,| 是用于更改的正则表达式元字符。您的r'00 LOG | Cycles Run: (.*?)' 示例正则表达式存在寻找00 LOG 或`Cycles Run: (.*?)` 的问题,这就是它不匹配任何内容的原因。
  • 既然Max>Current> 在同一行中,您如何确定要捕获的目标是哪一个?
  • 我们需要搜索 4 种不同的模式。有两行带有Virtual: Max>Current,每行分别带有VirtualActual。我们需要做不同的模式匹配来选择提到的第一个和最后一个值。

标签: python regex python-3.6 readline findall


【解决方案1】:

使用正则表达式

(?:(?:Cycles Run:[ \t]+)|(?:Current>[ \t]+))(\d+)

Demo

您可以按照以下方式做一些事情:

import re
pat=re.compile(r'(?:(?:Cycles Run:[ \t]+)|(?:Current>[ \t]+))(\d+)')
with open('test.txt','r') as f:   
    for line_num, line in enumerate(f):
        m=pat.search(line)
        if m:
            print(line_num, m.group(0))

【讨论】:

  • 我使用 group(0) 只是因为不清楚 OP 是否想将该值读入 dict 或什么。它识别捕获的值。
  • 非常感谢!在这里,您使用Current> 匹配了模式。如果我们有这样的模式怎么办:00 LOG ! Virtual: Max> ?????????? bytes (?.???? gb), Current> 640733184 bytes (?.???? gb).00 LOG ! Virtual: Max> 1082470400 bytes (?.???? gb), Current> ????????? bytes (?.???? gb).00 LOG ! Actual: Max> ????????? bytes (?.???? gb), Current> 472154112 bytes (?.???? gb).00 LOG ! Actual: Max> 861736960 bytes (?.???? gb), Current> ????????? bytes (?.???? gb).我们需要在四个不同的变量中选取这四个值。
  • 请用这些字符串更新您的问题。在评论中不清楚您在寻找什么。
  • 更新了原来的问题! :)
【解决方案2】:

您可以在此处使用两个lookbehinds 的交替:

(?<=Cycles Run:  )\d+|(?<= Current>  )\d+

正则表达式演示here.


Python 示例:

import re
text = '''
00 LOG     |   Cycles Run:  120001
00 LOG     !   Virtual: Max> 1082470400 bytes (1.0081 gb), Current>  640733184 bytes (0.5967 gb)
'''

pattern = re.compile(r'(?<=Cycles Run:  )\d+|(?<= Current>  )\d+')
matches = re.findall(pattern,text)
num_cycle = matches[0]
current = matches[1]

print(num_cycle,current)

打印:

120001 640733184

由于您在循环中重复该过程,因此建议在循环之前使用re.compile仅编译一次模式。

【讨论】:

    【解决方案3】:

    在这里我们搜索一些标识符(如cycles 并应用不同的正则表达式)

    import re
    with open('test.txt','r') as f:
        for line in f:
            if re.search(r'Cycles',line):
                m=re.findall(r'\d+$',line)
            else:
                m=re.findall(r'Current>  (\d+)',line)
            print(m)
    

    【讨论】:

    • 这可行,但似乎效率很低。模式至少应该在循环之前编译。
    • @Unbearable 文档声明the module-level matching functions are cached, so programs that use only a few regular expressions at a time needn’t worry about compiling regular expressions. 因为它是同一个表达式,我认为缓存会有所帮助。此外,正则表达式非常简单,没有前瞻/后视,这将节省大量时间。这显然不优雅。
    • 你是对的,看起来模式是cached,我的错。是的,lookarounds 可能很昂贵,但是如果使用它们,只需要一个 re 函数。
    猜你喜欢
    • 2016-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多