Устаревший в пользу нового ответа
Ответ justintime работает, говоря perl, что вы хотите назвать конец строки "\ n \ n", что является умными будет хорошо работать. Единственным исключением является то, что это должно точно соответствовать.При использовании используемого вами регулярного выражения создается впечатление, что в «пустых» строках могут быть пробелы, и в этом случае это не сработает.Кроме того, его метод разделит даже более чем на 2 переноса строки, что не было разрешено в ОП.
Для полноты, чтобы сделать это так, как вы просили, вам нужно вылить весь файл в переменную (еслифайл не такой большой, чтобы использовать всю вашу память, вероятно, в большинстве случаев нормально).
Тогда я бы, вероятно, сказал бы использовать функцию split
для разбиения блока текста на массив кусков.Ваш код будет выглядеть примерно так:
#!/usr/bin/perl
use strict;
use warnings;
my $file = 'yu';
my $text;
open(my $fh, '<', $file);
{
local $/; enables slurp mode inside this block
$text = <$fh>;
}
close($fh);
my @blocks = split(
/
(?<!\n)\n #check to make sure there isn't another \n behind this one
\s*\n #first whitespace only line
\s*\n #second "
(?!\n) #check to make sure there isn't another \n after this one
/x, # x flag allows comments and whitespace in regex
$text
);
Затем вы можете выполнять операции с массивом.Если я понимаю ваш комментарий к ответу justintime, вы хотите записать каждый блок в отдельный файл.Это будет выглядеть примерно так:
my $file_num = 1;
foreach my $block (@blocks) {
open(my $out, '>', $file_num++ . ".txt");
print $out $block;
}
Обратите внимание, что, поскольку вы открываете $ лексически (с помощью my
), когда он достигает конца блока foreach, переменная $ out умирает (то есть "выходит из области видимости«).Когда это происходит с лексическим дескриптором файла, файл автоматически закрывается.И вы можете сделать то же самое с методом justintime:
local $/ = "\n\n" ;
my $file_num = 1;
while (<>) {
open(my $out, '>', $file_num++ . ".txt");
print $out $block;
}