根据内容拆分linux中的文件

时间:2011-12-17 10:49:13

标签: linux file bash sed awk

我有一个大约400mb的电子邮件转储。我想将其拆分为.txt文件,每个文件中包含一封邮件。每封电子邮件都以指定doctype的标准HTML标头开头。

这意味着我将根据上述标题拆分文件。我如何在linux中进行操作?

5 个答案:

答案 0 :(得分:66)

如果您有mail.txt

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

<html>
    mail B
</html>

<html>
    mail C
</html>

运行csplit<html>

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

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

检查输出

$ 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

答案 1 :(得分:4)

csplit程序优雅地解决了您的问题:

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

答案 2 :(得分:2)

csplit是此问题的最佳解决方案。我以为我会发布一个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

答案 3 :(得分:1)

一些perl“魔法”是可行的......许多人会称之为丑陋但这里就是这样。

诀窍是用您想要的内容替换$/并阅读您的输入,如下:

#!/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;
}

编辑:修复,我总是忘记输入中包含$/。此外,第一个文件将始终为空,但随后可以轻松处理。

答案 4 :(得分: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替换为您的标头类型。