【问题标题】:How to recover only the second instance of a string in a text file?如何仅恢复文本文件中字符串的第二个实例?
【发布时间】:2015-11-07 16:26:52
【问题描述】:

我有大量格式相同的文本文件 (>1000)。

我感兴趣的文件部分类似于:

# event 9
num:     1
length:      0.000000
otherstuff: 19.9 18.8 17.7
length: 0.000000 176.123456

# event 10
num:     1
length:      0.000000
otherstuff: 1.1 2.2 3.3
length: 0.000000 1201.123456

我只需要定义变量的第二个实例的第二个索引值,在这种情况下是长度。有没有这样做的pythonic方式(即不是sed)?

我的代码如下:

with open(wave_cat,'r') as catID:
        for i, cat_line in enumerate(catID):
            if not len(cat_line.strip()) == 0:
                line    = cat_line.split()
                #replen = re.sub('length:','length0:','length:')
                if line[0] == '#' and line[1] == 'event':
                    num = long(line[2])
                elif line[0] == 'length:':
                    Length = float(line[2])

【问题讨论】:

  • 就是一个文件的全部内容?
  • 不,每个文件有超过 10 个事件,但格式都相同。编辑:我改变了上面的文件格式。

标签: python regex string if-statement for-loop


【解决方案1】:

如果您可以将整个文件读入内存,只需执行regex against the file contents:

for fn in [list of your files, maybe from a glob]:
    with open(fn) as f:
        try:
            nm=pat.findall(f.read())[1]
        except IndexError:
            nm=''
        print nm   

如果文件较大,请使用 mmap:

import re, mmap

nth=1
pat=re.compile(r'^# event.*?^length:.*?^length:\s[\d.]+\s(\d+\.\d+)', re.S | re.M)
for fn in [list of your files, maybe from a glob]:
    with open(fn, 'r+b') as f:
        mm = mmap.mmap(f.fileno(), 0)
        for i, m in enumerate(pat.finditer(mm)):
            if i==nth:
                print m.group(1)
                break

【讨论】:

    【解决方案2】:

    使用计数器:

    with open(wave_cat,'r') as catID:
        ct = 0
        for i, cat_line in enumerate(catID):
            if not len(cat_line.strip()) == 0:
                line    = cat_line.split()
                #replen = re.sub('length:','length0:','length:')
                if line[0] == '#' and line[1] == 'event':
                    num = long(line[2])
                elif line[0] == 'length:':
                    ct += 1
                    if ct == 2:
                        Length = float(line[2])
                        ct = 0
    

    【讨论】:

      【解决方案3】:

      你在正确的轨道上。除非您确实需要,否则推迟拆分可能会更快一些。此外,如果您正在扫描大量文件并且只想要第二个长度条目,那么一旦您看到它就可以节省大量时间来跳出循环。

      length_seen = 0
      elements = []
      with open(wave_cat,'r') as catID:
          for line in catID:
              line = line.strip()
              if not line:
                  continue
              if line.startswith('# event'):
                  element = {'num': int(line.split()[2])}
                  elements.append(element)
                  length_seen = 0
              elif line.startswith('length:'):
                  length_seen += 1
                  if length_seen == 2:
                      element['length'] = float(line.split()[2])
      

      【讨论】:

      • 这确实加快了速度,感谢您指出这一点!我还在中断之前添加了length_seen = 0,因为在单个文件中存在相同文本的多个副本。
      • 我已经对其进行了修改,以构建文件的元素列表,包括数字和长度。
      猜你喜欢
      • 1970-01-01
      • 2019-10-15
      • 2021-09-01
      • 1970-01-01
      • 2013-12-17
      • 2022-11-13
      • 2013-04-10
      • 1970-01-01
      • 2013-03-28
      相关资源
      最近更新 更多