2011-12-17 12 views
33

私は約400MBの電子メールダンプを持っています。これを各ファイルの1つのメールで構成される.txtファイルに分割します。すべての電子メールは、標準のHTMLヘッダーで始まり、doctypeを指定します。コンテンツに基づいてLinuxでファイルを分割する

これは、上記のヘッダーに基づいてファイルを分割する必要があることを意味します。どうすればLinuxで動くのですか?

+0

本当にメールダンプですか?メールヘッダーがまったくないということですか? Doctypeを指定する "標準HTMLヘッダー"とは何ですか? – fge

+0

"<!DOCTYPE html PUBLIC \" - // W3C // DTD HTML 4.01 Transitional // EN \ "> Greenhorn

答えて

54

あなたは<html>

$ csplit mail.txt '/^<html>$/' '{*}' 

- mail.txt => input file 
- /^<html>$/ => pattern match every `<html>` line 
- {*}   => repeat the previous pattern as many times as possible 

チェック出力によって分割するmail.txt

$ cat mail.txt 
<html> 
    mail A 
</html> 

<html> 
    mail B 
</html> 

<html> 
    mail C 
</html> 

実行csplitを持っている場合は

$ ls 
mail.txt xx00 xx01 xx02 xx03 

あなたはawk

$ awk '/<html>/{filename=NR".txt"}; {print >filename}' mail.txt 
$ ls 
1.txt 5.txt 9.txt mail.txt 
+0

は怖いです!私は同じことをやったと $のLS mail.txt XX00 と明らかにメールをしました.txtはxx00と同じです 修正はありますか? – Greenhorn

+0

@Ramprakash私の 'csplit'のverは' 8.5'です。たぶんあなたのパターンには{{}}がありません。マンページを確認してください。私はちょうど 'awk'ソリューションを追加します。あなたはそれを試すことができます。 – kev

+0

Awkは働いた:) ありがとう! – Greenhorn

1

これはいくつかのperl "magic"で実行できます...多くの人がこれを醜いと呼んでいますが、ここにはあります。

トリックは、あなたが望むもので$/を交換し、あなたの入力を読んで、のようなことです:

#!/usr/bin/perl -W 
use strict; 
my $i = 1; 

$/ = <<EOF; 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head> <xmeta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type"> 
EOF 

open INPUT, "/path/to/inputfile" or die; 

while (my $mail = <INPUT>) { 
    $mail = substr($mail, 0, index($mail, $/)); 
    open OUTPUT, ">/path/to/emailfile." . $i . ".txt" or die; 
    $i++; 
    print OUTPUT $mail; 
    close OUTPUT; 
} 

編集:固定、私はいつも$/が入力に含まれていることを忘れています。また、最初のファイルは常に空ですが、簡単に処理できます。

1

私はfgeに同意します。 perlとすると、ずっと簡単になります。このようなものを試すことができます -

#!/usr/bin/perl 

undef $/; 
$_ = <>; 
$n = 0; 

for $match (split(/(?=HEADER_FORMAT)/)) { 
     open(O, '>mail' . ++$n); 
     print O $match; 
     close(O); 
} 

HEADER_FORMATをあなたのヘッダータイプに置き換えてください。

+0

肯定的な先読みはうまくいくはずです。特にヘッダーにはメタ文字が含まれていないので、 'qr //'分割された正規表現を構築する。 – fge

4

csplitプログラムはエレガントにあなたの問題を解決:

csplit '/<!DOCTYPE.*/' $FILE 
+1

引数が間違った順序であり、意図したように、実際に行うには繰り返しが欠落している。 – qwertzguy

2

csplitでそれを行う場合、この問題に対する最善の解決策です。ちょうど私がこのタスクでperlに行く必要がないことを示すためにbash-solutionを投稿したいと思ったのです:

#!/usr/bin/bash 

MAIL='mail'  # path to huge mail-file 

#get linenumbers for all headers 
line_no=$(grep -n html $MAIL | cut -d: -f1) 

read -a LINES<<< $line_no 

file=0 
for i in $(seq 0 2 ${#LINES[@]}); do 
    start=${LINES[i]} 
    end=$((${LINES[i+1]}-1)) 
    echo $start, $end 
    sed -n "${start},${end}p" $MAIL > ${MAIL}${file}.txt 
    file=$((file+1)) 
done 
関連する問題