Разделение большого txt-файла на 200 меньших txt-файлов в регулярном выражении с использованием сценария оболочки в BASH - PullRequest
11 голосов
/ 10 февраля 2011

Привет, ребята. Надеюсь, тема достаточно ясна, я не нашел ничего конкретно об этом в ранее заданном бен.Я пытался реализовать это в Perl или Python, но я думаю, что, возможно, слишком стараюсь.

Существует ли простая команда / конвейер оболочки, которая разделит мой файл 4mb .txt на отдельные файлы .txt на основев начале и конце регулярного выражения?

Я приведу краткий пример файла ниже .. так что вы можете видеть, что каждая «история» начинается с фразы «X из XXX ДОКУМЕНТОВ», которая может быть использована для разделенияфайл.

Я думаю, что это должно быть легко, и я был бы удивлен, если 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 ]

22 голосов
/ 10 февраля 2011
awk '/[0-9]+ of [0-9]+ DOCUMENTS/{g++} { print $0 > g".txt"}' file

Пользователям OSX потребуется gawk, поскольку встроенный awk выдаст ошибку, такую ​​как awk: illegal statement at source line 1

Ruby (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
9 голосов
/ 10 февраля 2011

Как предлагалось в других решениях, для этого можно использовать csplit:

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

Я не нашел лучшего способа избавиться от напоминающего разделителя в разделенных файлах.

1 голос
/ 10 февраля 2011

Как сильно ты пробовал в 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);
0 голосов
/ 10 февраля 2011

Не проверено:

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
0 голосов
/ 10 февраля 2011

регулярное выражение для соответствия "X из XXX ДОКУМЕНТОВ"\ d {1,3} из \ d {1,3) ДОКУМЕНТОВ

чтение построчно и начало записи нового файла при совпадении с регулярным выражением должно быть в порядке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...