在linux中基于内容拆分文件

我有一个约400MB的电子邮件转储。 我想分割成.txt文件,每个文件中包含一个邮件。 每封电子邮件都以指定文档types的标准HTML标题开始。

这意味着我将不得不分裂我的文件基于上述的头。 我如何在Linux中去解决它?

Solutions Collecting From Web of "在linux中基于内容拆分文件"

如果你有一个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 

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

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

csplit是解决这个问题的最佳方案。 只是以为我会发布一个bash解决方案,以显示没有必要去perl这个任务:

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

我同意fge。 用perl就会简单得多。 你可以尝试这样的事情 –

 #!/usr/bin/perl undef $/; $_ = <>; $n = 0; for $match (split(/(?=HEADER_FORMAT)/)) { open(O, '>mail' . ++$n); print O $match; close(O); } 

HEADER_FORMAT替换为标题类型。

一些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; } 

编辑:固定,我总是忘记$/是包含在输入。 而且,第一个文件总是空的,但是可以很容易地处理。