私は約400MBの電子メールダンプを持っています。これを各ファイルの1つのメールで構成される.txtファイルに分割します。すべての電子メールは、標準のHTMLヘッダーで始まり、doctypeを指定します。コンテンツに基づいてLinuxでファイルを分割する
これは、上記のヘッダーに基づいてファイルを分割する必要があることを意味します。どうすればLinuxで動くのですか?
私は約400MBの電子メールダンプを持っています。これを各ファイルの1つのメールで構成される.txtファイルに分割します。すべての電子メールは、標準のHTMLヘッダーで始まり、doctypeを指定します。コンテンツに基づいてLinuxでファイルを分割する
これは、上記のヘッダーに基づいてファイルを分割する必要があることを意味します。どうすればLinuxで動くのですか?
あなたは<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
これはいくつかの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;
}
編集:固定、私はいつも$/
が入力に含まれていることを忘れています。また、最初のファイルは常に空ですが、簡単に処理できます。
私はfgeに同意します。 perl
とすると、ずっと簡単になります。このようなものを試すことができます -
#!/usr/bin/perl
undef $/;
$_ = <>;
$n = 0;
for $match (split(/(?=HEADER_FORMAT)/)) {
open(O, '>mail' . ++$n);
print O $match;
close(O);
}
HEADER_FORMAT
をあなたのヘッダータイプに置き換えてください。
肯定的な先読みはうまくいくはずです。特にヘッダーにはメタ文字が含まれていないので、 'qr //'分割された正規表現を構築する。 – fge
csplit
プログラムはエレガントにあなたの問題を解決:
csplit '/<!DOCTYPE.*/' $FILE
引数が間違った順序であり、意図したように、実際に行うには繰り返しが欠落している。 – qwertzguy
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
本当にメールダンプですか?メールヘッダーがまったくないということですか? Doctypeを指定する "標準HTMLヘッダー"とは何ですか? – fge
"<!DOCTYPE html PUBLIC \" - // W3C // DTD HTML 4.01 Transitional // EN \ ">