Разделение большого текстового файла на каждой пустой строке

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

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

снова отдельный файл anyN + 1.txt и т.д.

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

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

Разделить текстовый файл на несколько файлов и
https://unix.stackexchange.com/info/46325/how-can-i-split-a-text-file-into-multiple-text-files

Как изменить входные данные в командной строке, чтобы решить мою проблему?

Ответ 1

Настройка 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
$ 

Ответ 2

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 ); 
}

Просто так. <> - это "волшебный" дескриптор файла, в котором он считывает данные с каналами или из файлов, указанных в командной строке (открывает их и читает их). Это похоже на работу sed или grep.

Это можно свести к одному вкладышу:

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

Ответ 3

Вы можете использовать этот awk,

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

(ИЛИ)

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

Более читаемый формат:

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

Ответ 4

С пятницы, и я чувствую себя немного полезной...:)

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

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

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

Устанавливает разделитель записи как пустую строку, печатает каждую запись в виде отдельного файла с номерами 1, 2, 3 и т.д. Последний файл (только) заканчивается пустой строкой.

Ответ 6

Попробуйте это bash script также

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