在每个空行上拆分大文本文件

时间:2015-10-23 04:39:03

标签: bash perl awk

我将大文本文件拆分成多个较小的文件有点麻烦。我的文本文件的语法如下:

dasdas #42319 blaablaa 50 50
content content
more content
content conclusion

asdasd #92012 blaablaa 30 70
content again
more of it
content conclusion

asdasd #299 yadayada 60 40
content
content
contend done
...and so on

(dasdas#42319 blaablaa 50 50,内容内容,更多内容和内容结论都是他们自己单独的行,后面跟一个空白行是该信息表的结尾。我文件中的典型信息表有10个之间的任何地方-40行。)

我希望将此文件拆分为n个较小的文件,其中n是内容表的数量 那是

dasdas #42319 blaablaa 50 50
content content
more content
content conclusion

将是它自己的单独文件,(whateverN.txt)

asdasd #92012 blaablaa 30 70
content again
more of it
content conclusion

再一个单独的文件,无论N + 1.txt等等。

似乎awkPerl是非常好的工具,但在语法之前从未使用它们有点莫名其妙。

我发现这两个问题几乎与我的问题相对应,但未能修改语法以满足我的需求。

Split text file into multiple files&
https://unix.stackexchange.com/questions/46325/how-can-i-split-a-text-file-into-multiple-text-files

如何修改命令行输入,以便解决我的问题?

9 个答案:

答案 0 :(得分:24)

RS设置为null会告诉awk使用一个或多个空行作为记录分隔符。然后,您只需使用NR设置与每条新记录对应的文件名称:

 awk -v RS= '{print > ("whatever-" NR ".txt")}' file.txt
  

RS:   这是awk的输入记录分隔符。它的默认值是一个包含单个换行符的字符串,这意味着输入记录由一行文本组成。 它也可以是空字符串,在这种情况下,记录由空行或正则表达式分隔,在这种情况下,记录由输入文本中正则表达式的匹配分隔。

$ cat file.txt
dasdas #42319 blaablaa 50 50
content content
more content
content conclusion

asdasd #92012 blaablaa 30 70
content again
more of it
content conclusion

asdasd #299 yadayada 60 40
content
content
contend done

$ awk -v RS= '{print > ("whatever-" NR ".txt")}' file.txt

$ ls whatever-*.txt
whatever-1.txt  whatever-2.txt  whatever-3.txt

$ cat whatever-1.txt 
dasdas #42319 blaablaa 50 50
content content
more content
content conclusion

$ cat whatever-2.txt 
asdasd #92012 blaablaa 30 70
content again
more of it
content conclusion

$ cat whatever-3.txt 
asdasd #299 yadayada 60 40
content
content
contend done
$ 

答案 1 :(得分:3)

Perl有一个称为输入记录分隔符的有用功能。 $/

这是'标记'用于在读取文件时分离记录。

所以:

#!/usr/bin/env perl
use strict;
use warnings;

local $/ = "\n\n"; 
my $count = 0; 

while ( my $chunk = <> ) {
    open ( my $output, '>', "filename_".$count++ ) or die $!;
    print {$output} $chunk;
    close ( $output ); 
}

就像那样。 <>是魔法&#39; filehandle,因为它读取管道数据或从命令行指定的文件(打开它们并读取它们)。这与sedgrep的工作方式类似。

这可以减少到一个班轮:

perl -00 -pe 'open ( $out, '>', "filename_".++$n ); select $out;'  yourfilename_here

答案 2 :(得分:2)

您可以使用此awk

awk 'BEGIN{file="content"++i".txt"} !NF{file="content"++i".txt";next} {print > file}' yourfile

(OR)

awk 'BEGIN{i++} !NF{++i;next} {print > "filename"i".txt"}' yourfile

更易读的格式:

BEGIN {
        file="content"++i".txt"
}
!NF {
        file="content"++i".txt";
        next
}
{
        print > file
}

答案 3 :(得分:1)

您可以使用csplit命令:

csplit \
    --quiet \
    --prefix=whatever \
    --suffix-format=%02d.txt \
    --suppress-matched \
    infile.txt /^$/ {*}

POSIX csplit仅使用简短选项,不知道--suffix--suppress-matched,因此这需要GNU csplit

这是选项的作用:

  • --quiet –禁止输出文件大小
  • --prefix=whatever –使用whatever代替默认的xx文件名前缀
  • --suffix-format=%02d.txt –将.txt附加到默认的两位数字后缀
  • --suppress-matched –不包括与分割输入的模式匹配的行
  • /^$/ {*} –尽可能频繁地在模式“空行”(/^$/)({*})上拆分

答案 4 :(得分:0)

因为星期五,我感觉有点帮助... :)

试试这个。如果文件小到你暗示最简单的方法就是一次只读它并在内存中工作。

use strict;
use warnings;

# slurp file
local $/ = undef;
open my $fh, '<', 'test.txt' or die $!;
my $text = <$fh>;
close $fh;

# split on double new line
my @chunks = split(/\n\n/, $text);

# make new files from chunks
my $count = 1;
for my $chunk (@chunks) {
    open my $ofh, '>', "whatever$count.txt" or die $!;
    print $ofh $chunk, "\n";
    close $ofh;
    $count++;
}

perl文档可以解释您不理解的任何单个命令,但此时您也应该查看教程。

答案 5 :(得分:0)

awk -v RS="\n\n" '{for (i=1;i<=NR;i++); print > i-1}' file.txt

将记录分隔符设置为空行,将每个记录打印为编号为1,2,3等的单独文件。最后一个文件(仅)以空行结束。

答案 6 :(得分:0)

尝试这个bash脚本

#!/bin/bash
i=1
fileName="OutputFile_$i"
while read line ; do 
if [ "$line"  == ""  ] ; then
 ((++i))
 fileName="OutputFile_$i"
else
 echo $line >> "$fileName"
fi
done < InputFile.txt

答案 7 :(得分:0)

如果出现“打开文件过多”错误,如下所示...

awk: whatever-18.txt makes too many open files
 input record number 18, file file.txt
 source line number 1

您可能需要在创建新文件之前关闭新创建的文件,如下所示。

awk -v RS= '{close("whatever-" i ".txt"); i++}{print > ("whatever-" i ".txt")}' file.txt

答案 8 :(得分:0)

您也可以尝试split -p "^$"