我有这样的文字:
37 7 -------------- No aaa
40 0 -------------- No bbb
xxx zzy
aa bb cc
42 2 -------------- No ccc
xxx zyz
a b c d
43 3 -------------- No ddd
xy zz
a a
a a
c
52 5 -------------- No eee
yyyx zzz
当我用awk处理它时,我得到:
awk '{if($1+0==$1) p=$1 FS $2 FS $3 FS $4 FS $5; else $0=p FS $0}1' /tmp/test3 | column -t
37 7 -------------- No aaa
37 7 -------------- No aaa xxx zzz
40 0 -------------- No bbb
40 0 -------------- No bbb xxx zzy
40 0 -------------- No bbb aa bb cc
42 2 -------------- No ccc
42 2 -------------- No ccc xxx zyz
42 2 -------------- No ccc a b c d
43 3 -------------- No ddd
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
52 5 -------------- No eee yyyx zzz
我需要获取以下输出:
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
预先感谢您的帮助!我也尝试过
awk '/-/{base=$0; next} {print base, $0}' /tmp/test4 | column -t
,如建议的那样,但是如果连续的行以数字开头,则会删除以数字开头的第一行。
这个sed咒语解决了我的问题: sed -r':a; N; / ^ [0-9]。 \ n [0-9] / {P; D} ;: b; s /^(.)\ n( 。)/ \ 1 \ 2 \ n \ 1 /; P; s/。 \ n //; $ d; N; / \ n [0-9] / D; bb'/ tmp / test2
另一个问题:如果我在输出行中有8列以上,是否可以修改sed命令,以便将第9、10和11列移至新行并在其前复制前5列? / p>
假设我有以下3行:
42 2 -------------- No ccc xxx zyz 42 2 -------------- No ccc a b c d e f 43 3 -------------- No ddd xy zz
我想得到:
42 2 -------------- No ccc xxx zyz 42 2 -------------- No ccc a b c 42 2 -------------- No ccc d e f 43 3 -------------- No ddd xy zz
答案 0 :(得分:0)
这可能对您有用(GNU sed):
sed -r ':a;N;s/^(.*)\n\1(.)/\1\2/;ta;P;D' file
打开至少两行的窗口。如果前一行的开头与当前行的头完全相同,并且当前行较长,则删除前一行并重复。否则,打印然后删除第一行并重复。
这是根据awk脚本运行的。
要使用原始数据实现相同的解决方案,请使用:
sed -r ':a;N;/^[0-9].*\n[0-9]/{P;D};:b;s/^(.*)\n(.*)/\1 \2\n\1/;P;s/.*\n//;$d;N;/\n[0-9]/D;bb' file
答案 1 :(得分:0)
以下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 = ();
}
这使用splice一次删除输出的文本的前三列,并用最后一个数字行的(五)列进行打印。这是在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
答案 2 :(得分:0)
您可以按如下所述使用此命令,希望对您有所帮助
awk '{if($1+0==$1) p=$1 FS $2 FS $3 FS $4 FS $5; else $0=p FS $0}1' test.txt | sort -k2 | column -t | awk '{ if ($6 >= " ") { print } }'