2017-06-16 9 views
1

私は複数のファイルに分割したい平文ファイルを持っています。私はへの(および含む)ENDをBEGIN(を含む)から、各ブロックを分割したい再帰を使ってPythonの区切り文字に基づいてテキストファイルを分割する

-----BEGIN CERTIFICATE----- 
text1 
text2 
text3 
-----END CERTIFICATE----- 
-----BEGIN CERTIFICATE----- 
text4 
text5 
text6 
-----END CERTIFICATE----- 
-----BEGIN CERTIFICATE----- 
text7 
text8 
text9 
-----END CERTIFICATE----- 
-----BEGIN CERTIFICATE----- 
text10 
text11 
text12 
-----END CERTIFICATE----- 

:ファイル形式は、このようなものです。

with open('/Users/arl/Downloads/bundle.pem', 'r') as cert_file: 
    cert = cert_file.readlines() 

def parse_file(filename=None, variable=None): 
    with open(filename, "w") as variable: 
     for line in cert: 
      if "BEGIN" in line: 
       variable.write(line) 
       continue 
      elif "END" in line: 
       variable.write(line) 
       parse_file(filename="int1.pem", variable="int1_file") 
       parse_file(filename="int2.pem", variable="int2_file") 
       parse_file(filename="end.pem", variable="end_file") 
      print line.rstrip() 
      variable.write(line) 
     variable.close() 

parse_file(filename="root.pem", variable="root_file") 

エラーを私は現在入手:

この

は私がこれまでに書かれたものである

parse_file(filename="int1.pem", variable="int1_file") 
    File "splitter.py", line 12, in parse_file 
    parse_file(filename="int1.pem", variable="int1_file") 
    File "splitter.py", line 17, in parse_file 
    variable.close() 
RuntimeError: maximum recursion depth exceeded while calling a Python object 

そしてだけroot.pemint1.pemが書かれている(との両方が同じコンテンツを、持っていた彼らすべきではありません)

ファイルを解析して、新しいブロックをそれぞれ新しいファイルに書き込むには、何が必要ですか?関数が新しいパラメータでそれ自身を呼び出すためのループの正しい点はどれですか?正規表現経由

おかげ

+0

あなたの機能だけで実際にはグローバルファイル(CERT)から読み込むので、あなたの再帰呼び出しは、単にそれが何度も何度もそのファイルから読み込ませる、したがって、無限再帰。 –

+0

あなたは何をしようとしているのか、なぜ再帰を使用するのかは明確ではありません。また、 'variable'をファイルポインタで上書きするので、パラメータは無効になります。 root.pem、int1.pem、int2.pem、end.pemにそれぞれbundle.pemのセクションが1つ含まれるようにしますか? – Stuart

+0

@AlanLeuthard:はい、今は分かります。私は、ファイルの先頭から始めるのではなく、最後にどこから読み続けるかを理解しようとしています。 – ARL

答えて

1

私は再帰がここに有用であろう見ることができない代わりに - あなたは、出力ファイル名のリストを作成し、iterを使用してそれらを反復処理ができ、 next、 "BEGIN"が発生したときにファイルを開き、 "END"が発生したときに同じファイルを閉じます。

def parse_file(input_file, output_files): 
    filenames = iter(output_files) 
    with open(input_file, 'r') as cert_file: 
     for line in cert_file: 
      if "BEGIN" in line: 
       output = open(filenames.next(), 'w') 
      output.write(line) 
      if "END" in line: 
       output.close() 
    output.close() # just in case not already closed 

input_file = '/Users/arl/Downloads/bundle.pem' 
output_files = ['root.pem', 'int1.pem', 'int2.pem', 'end.pem'] 
parse_file(input_file=input_file, output_files=output_files) 

空白や「BEGIN」と「END」の間にある他のコンテンツがある場合にエラーが発生します。それが問題であれば、出力ファイルが開かれたことを確認する行を追加することができます。

def parse_file(input_file, output_files): 
    filenames = iter(output_files) 
    output = None 
    with open(input_file, 'r') as cert_file: 
     for line in cert_file: 
      if "BEGIN" in line: 
       output = open(filenames.next(), 'w') 
      if output and not output.closed: 
       output.write(line) 
      if "END" in line: 
       output.close() 
    output.close() 

または同等に、ネストされたループを使用します。別の答えに

def parse_file(input_file, output_files): 
    output = None 
    with open(input_file, 'r') as cert_file: 
     for output_file in output_files: 
      for line in cert_file: 
       if "BEGIN" in line: 
        output = open(output_file, 'w') 
       if output and not output.closed: 
        output.write(line) 
       if "END" in line: 
        output.close() 
        break # breaks out of inner loop and gets next output_file 
    output.close() 
1

import re 

content = ''' 
-----BEGIN CERTIFICATE----- 
text1 
text2 
text3 
-----END CERTIFICATE----- 
-----BEGIN CERTIFICATE----- 
text4 
text5 
text6 
-----END CERTIFICATE----- 
-----BEGIN CERTIFICATE----- 
text7 
text8 
text9 
-----END CERTIFICATE----- 
-----BEGIN CERTIFICATE----- 
text10 
text11 
text12 
-----END CERTIFICATE----- 
''' 

content = content.strip('\n') 

pattern = re.compile('\-\-\-\-\-BEGIN CERTIFICATE\-\-\-\-\-((.|\n)*?)\-\-\-\-\-END CERTIFICATE\-\-\-\-\-') 
certs = re.findall(pattern, content) 
for cert in certs: 
    cert_content = cert[0].strip('\n') 
    print cert_content 
    print 
0

類似しますが、手動でファイルの名前をリストするあなたを必要とせずに、BEGINとENDの間に複数のセグメントが可能になります。スクリプトは出力する最終ファイルの名前を変更します。他の人が触れたように、再帰の必要はありません。 (再帰はあなたが非常識になります。)

collect = False 
file_number = -1 
with open('big_file.txt') as big: 
    for line in big.readlines(): 
     if line.startswith('-----BEGIN'): 
      collect = True 
      file_number += 1 
      little = open('int%s.pem' % file_number, 'w') 
      continue 
     elif line.startswith('-----END'): 
      little.close() 
      collect = False 
     else: 
      little.write(line) 

import os 
os.rename('int%s.pem' % file_number, 'end.pem') 
関連する問題