Скрипт Perl, приведенный ниже, принимает следующие требования:
Вход содержит чередующиеся блоки строк, начинающиеся либо с числа, либо с не числа, где за каждым блоком числовых строк следует блок текста.линий. Обновлено : Для вывода первых пяти столбцов из последней числовой строки из ее блока необходимо добавить к каждой из текстовых строк непосредственно следующего текстового блока.Другие текстовые строки печатаются как есть.
Код собирает номера и текстовые строки в своих буферах.Они обрабатываются и очищаются, как только мы добираемся до первой строки следующего блока числовых строк, то есть когда оба буфера не пусты.
use warnings;
use strict;
use feature 'say';
my $file = shift @ARGV || 'default_filename.txt';
die "Usage: $0 file\n" if not $file;
open my $fh, '<', $file or die "Can't open $file: $!";
my (@text, @nums);
while (my $line = <$fh>) {
chomp $line;
if ($line =~ /^[^0-9]/) {
push @text, $line;
if (eof) {
process_buffers(\@nums, \@text);
last
}
next;
}
elsif (@nums and @text) {
process_buffers(\@nums, \@text);
}
push @nums, $line;
}
sub process_buffers {
my ($rnums, $rtext) = @_;
# Remove last number line from array and take its first five columns
my @last_num_line_cols = (split ' ', pop @$rnums)[0..4];
# Print other number lines; all consecutive spaces replaced by tabs
say for map { s/\s+/\t/gr } @$rnums;
# Print text lines prepended by five columns of last number line
foreach my $text_line (@$rtext) {
say join "\t", @last_num_line_cols, $text_line;
}
@$rtext = ();
@$rnums = ();
}
Условие, включающее eof вышенеобходим для обработки последней партии числовых и текстовых блоков, поскольку никакой другой тест не может работать с последней строкой.Его размещение предполагает, что последняя строка должна быть текстовой строкой, что следует из моего предположения о требованиях.
Это печатает
37 7 -------------- No aaa
40 0 -------------- No bbb xxx zzy
40 0 -------------- No bbb aa bb cc
42 2 -------------- No ccc xxx zyz
42 2 -------------- No ccc a b c d
43 3 -------------- No ddd xy zz
43 3 -------------- No ddd a a
43 3 -------------- No ddd a a
43 3 -------------- No ddd c
52 5 -------------- No eee yyyx zzz
(выровнено на вкладках, как и ожидалось при вводе и требуетсяна выходе)
Обновление Ограничить ширину вывода до 8 столбцов, как описано в обновлении вопроса
Использовать эту модифицированную версию функции обработки
sub process_buffers_fmt {
my ($rnums, $rtext) = @_;
my @last_num_line_cols = (split ' ', pop @$rnums)[0..4];
say for map { s/\s+/\t/gr } @$rnums;
# Format output lines to 8 columns at most
foreach my $text_line (@$rtext) {
my @text_cols = split ' ', $text_line;
while (my @prn_text_cols = splice @text_cols, 0, 3) {
say join "\t", @last_num_line_cols, @prn_text_cols;
}
}
@$rtext = ();
@$rnums = ();
}
При этом используется сращивание для удаления первых трех столбцов текстового вывода за раз и печати их с (пятью) столбцами последней числовой строки.Это делается в цикле while
, поэтому он останавливается, когда @text_cols
полностью обработан (напечатан).
Для проверки я добавляю к текстовому блоку после числовой строки 43 3 ...
во входном файле следующие
a b c d e f g h i j k
, и выходные данные основной программы получают эти дополнительные строки
43 3 -------------- No ddd a b c
43 3 -------------- No ddd d e f
43 3 -------------- No ddd g h i
43 3 -------------- No ddd j k
Входной файл, который я использую для проверки всех требований и обновлений, -
37 7 -------------- No aaa MORE COLUMNS
40 0 -------------- No bbb
xxx zzy
aa bb cc
42 2 -------------- No ccc
xxx zyz
a b c d
43 3 -------------- No ddd AND YET MORE
xy zz
a a
a a
c
a b c d e f g h i j k
52 5 -------------- No eee
yyyx zzz
, а вывод программы (с функцией process_buffers_fmt
) -
37 7 -------------- No aaa MORE COLUMNS
40 0 -------------- No bbb xxx zzy
40 0 -------------- No bbb aa bb cc
42 2 -------------- No ccc xxx zyz
42 2 -------------- No ccc a b c
42 2 -------------- No ccc d
43 3 -------------- No ddd xy zz
43 3 -------------- No ddd a a
43 3 -------------- No ddd a a
43 3 -------------- No ddd c
43 3 -------------- No ddd a b c
43 3 -------------- No ddd d e f
43 3 -------------- No ddd g h i
43 3 -------------- No ddd j k
52 5 -------------- No eee yyyx zzz