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- と 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プログラマーなので、あなたの解決策をほとんど理解していませんが、不必要な反復がたくさん行われているようです。最初にファイルを読み込み、次に。の項目ごとにファイルを1回繰り返しますname_listnewfileまた、後で実際にファイルに書き込むために繰り返し処理する予定があるかどうかもわかりません。

これが私がそれを行う方法ですが、それが最もPythonのように見えるソリューションではないことを私は理解しています。ただし、ファイルを反復処理するのは1回だけです。(免責事項として、私はこれをテストしませんでした。)

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 に答える