6

多くのソリューションが存在しますが、ここでの特異性は、ライン内で分割できるようにする必要があることです。カットはパターンの直前に発生する必要があります。元:

インファイル:

<?xml 1><blabla1>
<blabla><blabla2><blabla>
<blabla><blabla>
<blabla><blabla3><blabla><blabla>
<blabla><blabla><blabla><?xml 4>
<blabla>
<blabla><blabla><blabla>
<blabla><?xml 2><blabla><blabla>

パターンでなる必要があります<?xml

出力ファイル 1:

<?xml 1><blabla1>
<blabla><blabla2><blabla>
<blabla><blabla>
<blabla><blabla3><blabla><blabla>
<blabla><blabla><blabla>

アウトファイル 2:

<?xml 4>
<blabla>
<blabla><blabla><blabla>
<blabla>

Outfile3:

<?xml 2><blabla><blabla>

実際、ここperlで検証された回答のスクリプトは、私の小さな例ではうまく機能します。しかし、より大きな (約 6GB) 実際のファイルに対してエラーが発生します。エラーは次のとおりです。

panic: sv_setpvn called with negative strlen at /home/.../split.pl line 7, <> chunk 1.

コメントする権限がないので、新しい投稿を開始しました。そして最後に、Python私はそれをよりよく理解しているので、解決策はさらに高く評価されます.

4

4 に答える 4

13

これは、すべてを RAM に読み込まずに分割を実行します。

def files():
    n = 0
    while True:
        n += 1
        yield open('/output/dir/%d.part' % n, 'w')


pat = '<?xml'
fs = files()
outfile = next(fs) 

with open(filename) as infile:
    for line in infile:
        if pat not in line:
            outfile.write(line)
        else:
            items = line.split(pat)
            outfile.write(items[0])
            for item in items[1:]:
                outfile = next(fs)
                outfile.write(pat + item)

警告: パターンが複数の行にまたがっている場合 (つまり、"\n" が含まれている場合)、これは機能しません。この場合は、 mmap ソリューションを検討してください。

于 2012-10-03T21:59:32.803 に答える
7

Perlは、ファイル全体をメモリに丸呑みする代わりに、大きなファイルを1行ずつ解析できます。これが短いスクリプトです(説明付き):

perl -n -E 'if (/(.*)(<\?xml.*)/ ) {
   print $fh $1 if $1;
   open $fh, ">output." . ++$i;
   print $fh $2;
} else { print $fh $_ }'  in.txt

perl -n-nフラグは、ファイルを1行ずつループします(内容を$ _に設定します)

-E:次のテキストを実行します(Perlはデフォルトでファイル名を想定しています)

if (/(.*)(<\?xml.*) )行が一致する場合は、<?xmlその行を(正規表現の一致を使用して)$1と$2に分割します。

print $fh $1 if $1行の先頭を古いファイルに出力します。

open $fh, ">output.". ++$i;書き込み用の新しいファイルハンドルを作成します。

print $fh $2行の残りを新しいファイルに印刷します。

} else { print $fn $_ }行が一致しなかった場合は<?xml、現在のファイルハンドルに出力してください。

注:このスクリプトは、入力ファイルが。で始まることを前提としています<?xml

于 2012-10-04T02:00:13.970 に答える
5

そのサイズのファイルの場合、おそらくmmapモジュールを使用することになるので、ファイルを自分でチャンクアップする必要はありません。そこのドキュメントから:

メモリ マップト ファイル オブジェクトは、文字列とファイル オブジェクトの両方のように動作します。ただし、通常の文字列オブジェクトとは異なり、これらは変更可能です。文字列が想定されるほとんどの場所で mmap オブジェクトを使用できます。たとえば、re モジュールを使用して、メモリ マップト ファイルを検索できます。それらは可変であるため、 を実行して単一の文字をobj[index] = 'a'変更したり、スライスに割り当てて部分文字列を変更したりできます: obj[i1:i2] = '...'。また、現在のファイル位置から開始して、ファイル内の別の位置までデータを読み書きすることもできますseek()

<?xml #>以下は、ファイル内で が出現するたびに検索する方法を示す簡単な例です。チャンクを新しいファイルに書き込むことができますが、その部分は書きません。

import mmap
import re

# a regex to match the "xml" nodes
r = re.compile(r'\<\?xml\s\d+\>')

with open('so.txt','r+b') as f:
    mp = mmap.mmap(f.fileno(),0)
    for m in r.finditer(mp):
        # here you can start collecting the starting positions and 
        # writing chunks to new files 
        print m.start()
于 2012-10-03T22:03:55.167 に答える
0

検索用語を分割するだけです

for i,part in enumerate(my_xml_Text_string.split("<?xml")):
    if not part.strip():continue # make sure its not empty
    with open("file%d.xml"%i,"w") as f: #open a file to write to
         f.write("<?xml"+part) #write the content putting your search term back in
于 2012-10-03T21:45:11.203 に答える