使用BASH中的shell脚本将大型文本文件拆分为正则表达式中的200个较小的txt文件

时间:2011-02-10 00:10:23

标签: regex bash shell unix scripting

大家好,我希望这个主题足够清楚,我在前面提到的bin中没有找到任何具体的内容。我试过在Perl或Python中实现它,但我想我可能会太努力了。

是否有一个简单的shell命令/管道将基于开头和结尾的正则表达式将我的4mb .txt文件拆分成单独的.txt文件?

我提供了以下文件的简短示例..因此您可以看到每个“故事”都以短语“X XXX of XXX DOCUMENTS”开头,可以用来分割文件。

我认为这应该很容易,如果bash无法做到这一点我会感到惊讶 - 比Perl / Py更快。

这是:

                           1 of 999 DOCUMENTS


              Copyright 2011 Virginian-Pilot Companies LLC
                          All Rights Reserved
                   The Virginian-Pilot(Norfolk, VA.)

...



                           3 of 999 DOCUMENTS


                  Copyright 2011 Canwest News Service
                          All Rights Reserved
                          Canwest News Service

...

提前感谢您的帮助。

罗斯

5 个答案:

答案 0 :(得分:22)

awk '/[0-9]+ of [0-9]+ DOCUMENTS/{g++} { print $0 > g".txt"}' file
  

OSX用户需要gawk,因为内置awk会产生错误,例如awk: illegal statement at source line 1

红宝石(1.9 +)

#!/usr/bin/env ruby
g=1
f=File.open(g.to_s + ".txt","w")
open("file").each do |line|
  if line[/\d+ of \d+ DOCUMENTS/]
    f.close
    g+=1
    f=File.open(g.to_s + ".txt","w")
  end
  f.print line
end

答案 1 :(得分:9)

正如其他解决方案中所建议的那样,您可以使用csplit

csplit csplit.test '/^\.\.\./' '{*}' && sed -i '/^\.\.\./d' xx*

我还没有找到更好的方法来摆脱拆分文件中的怀旧分隔符。

答案 2 :(得分:1)

你在Perl中尝试过多难?

修改这是一种更快的方法。它拆分文件然后打印零件文件。

use strict;
use warnings;

my $count = 1;

open (my $file, '<', 'source.txt') or die "Can't open source.txt: $!";

for (split /(?=^.*\d+[^\S\n]*of[^\S\n]*\d+[^\S\n]*DOCUMENTS)/m, join('',<$file>))
{
    if ( s/^.*(\d+)\s*of\s*\d+\s*DOCUMENTS.*(\n|$)//m )
    {
        open (my $part, '>', "Part$1_$count.txt") 
            or die "Can't open Part$1_$count for output: $!";
        print $part $_;
        close ($part);
        $count++;
    }
}
close ($file);

这是逐行方法:

use strict;
use warnings;

open (my $masterfile, '<', 'yourfilename.txt') or die "Can't open yourfilename.txt: $!";

my $count = 1;
my $fh;

while (<$masterfile>) {
    if ( /(?<!\d)(\d+)\s*of\s*\d+\s*DOCUMENTS/ ) {
        defined $fh and close ($fh);
        open ($fh, '>', "Part$1_$count.txt") or die "Can't open Part$1_$count for  output: $!";
        $count++;
        next;
    }
    defined $fh and print $fh $_;
}
defined $fh and close ($fh);
close ($masterfile);

答案 3 :(得分:0)

匹配“XXX文件的X”的正则表达式是
\ d {1,3} \ d {1,3}文件

逐行阅读并开始在正则表达式匹配时写入新文件应该没问题。

答案 4 :(得分:-1)

未测试:

base=outputfile
start=1
pattern='^[[:blank:]]*[[:digit:]]+ OF [[:digit:]]+ DOCUMENTS[[:blank:]]*$

while read -r line
do
    if [[ $line =~ $pattern ]]
    then
        ((start++))
        printf -v filecount '%4d' $start
        >"$base$filecount"    # create an empty file named like foo0001
    fi
    echo "$line" >> "$base$filecount"
done