2

我有一个很大的文件,像这样:

[图案1]
第1行
线2
第 3 行
...
...
[结束模式]
[模式2]
第1行
线2
...
...
[结束模式]

我需要在另一个文件中提取变量起始模式 [PATTERN1] 和另一个定义模式 [END PATTERN] 之间的行,仅用于某些特定的起始模式。
例如:

[模式2]
第1行
线2
...
...
[结束模式]

我已经使用以下代码使用较小的文件做同样的事情:

FILE=open('myfile').readlines()

newfile=[]
for n in name_list:
    A = FILE[[s for s,name in enumerate(FILE) if n in name][0]:]
    B = A[:[e+1 for e,end in enumerate(A) if 'END PATTERN' in end][0]]
    newfile.append(B)

其中 'name_list' 是一个包含我需要的特定启动模式的列表。

有用!!但我想有更好的方法来处理大文件,而不使用 .readlines() 命令。
任何人都可以帮助我吗?

多谢!

4

5 回答 5

4

考虑:

# hi
# there
# begin
# need
# this
# stuff
# end
# skip
# this

with open(__file__) as fp:
    for line in iter(fp.readline, '# begin\n'):
        pass
    for line in iter(fp.readline, '# end\n'):
        print line

打印“需要这个东西”

更灵活(例如允许重新模式匹配)是使用 itertools drop- and takewhile:

with open(__file__) as fp:
    result = list(itertools.takewhile(lambda x: 'end' not in x, 
        itertools.dropwhile(lambda x: 'begin' not in x, fp)))
于 2012-06-22T12:51:19.523 回答
4

使用类似的东西

import re

START_PATTERN = '^START-PATTERN$'
END_PATTERN = '^END-PATTERN$'

with open('myfile') as file:
    match = False
    newfile = None

    for line in file:
        if re.match(START_PATTERN, line):
            match = True
            newfile = open('my_new_file.txt', 'w')
            continue
        elif re.match(END_PATTERN, line):
            match = False
            newfile.close()
            continue
        elif match:
            newfile.write(line)
            newfile.write('\n')

这将迭代文件而不将其全部读入内存。它还直接写入您的新文件,而不是附加到内存中的列表。如果您的来源足够大,那也可能成为问题。

显然,您可能需要对此代码进行大量修改;可能不需要正则表达式模式来匹配开始/结束行,在这种情况下,将其替换为if 'xyz' in line.

于 2012-06-22T12:51:37.620 回答
1

我是一个新的 python 程序员,所以我几乎不理解你的解决方案,但似乎有很多不必要的迭代正在进行。首先你读入文件,然后对文件中的每个项目迭代一次name_list。另外,我不知道您是否打算newfile稍后进行迭代以将其实际写入文件。

这就是我的做法,尽管我意识到这不是看起来最像 Python 的解决方案。不过,您只会对文件进行一次迭代。(作为免责声明,我没有对此进行测试。)

patterns = {'startPattern1':"endPattern1", 'startPattern2':"endPattern2", 'startPattern3':"endPattern3"}

fileIn = open(filenameIn, 'r')
fileOut = open(filenameOut, 'w')
targetEndPattern = None

for line in fileIn:
   if targetEndPattern is not None:
       if line == targetEndPattern:
           targetEndPattern = None
       else:
           fileOut.write(line + "\n")
   elif line in patterns:
       targetEndPattern = patterns[line]

编辑:如果您期望模式按特定顺序排列,则必须修改此解决方案。我在假设模式的顺序无关紧要但每个开始模式都匹配特定的结束模式的假设下编写了这个。

于 2012-06-22T12:58:01.593 回答
1

我认为这与您的代码所做的相同:

FILE=open('myfile').readlines()

newfile=[]

pattern = None
for line in FILE:
    if line[0] == "[" and line[-1] == "]":
        pattern = line[1:-1]
        if pattern == "END PATTERN":
            pattern = None
        continue
    elif pattern is not None and pattern in name_list:
        newfile.append(line)

这样,您只需遍历所有行一次,并在您进行时填写您的列表。

于 2012-06-22T12:44:38.093 回答
1

我会选择基于生成器的解决方案

#!/usr/bin/env python    
start_patterns = ('PATTERN1', 'PATTERN2')
end_patterns = ('END PATTERN')

def section_with_bounds(gen):
  section_in_play = False
  for line in gen:
    if line.startswith(start_patterns):
      section_in_play = True
    if section_in_play:
      yield line
    if line.startswith(end_patterns):
      section_in_play = False

with open("text.t2") as f:
  gen = section_with_bounds(f)
  for line in gen:
    print line
于 2012-06-22T16:22:56.470 回答