在Linux中的某个标题下添加列

时间:2015-07-29 16:49:58

标签: linux parsing awk sed

在Linux的文本文件中,我有以下形式的数据:

23:31:39
20 0 24436 404 56 R 2.7 0.0 1:38.52
20 0 43064 20112 4484 R 0.8 0.1 0:00.12
20 0 27116 5152 3856 S 0.3 0.0 0:00.05
20 0 24952 4672 3708 S 0.0 0.0 0:00.05
23:31:54
20 0 24436 404 56 R 2.7 0.0 1:38.93
20 0 24952 4672 3708 S 0.0 0.0 0:00.05
23:32:09
20 0 24436 404 56 R 2.6 0.0 1:39.32
20 0 24952 4672 3708 S 0.0 0.0 0:00.05
23:32:24
20 0 24436 404 56 R 2.9 0.0 1:39.76
20 0 24952 4672 3708 S 0.0 0.0 0:00.05

我想在每个时间戳下添加某些列,这样当我添加说...第1列时,我得到的内容将是:

23:31:39
80
23:31:54
40
23:32:09
40
23:32:24
40

当我添加第1列和第7列时,我得到:

23:31:39
80 3.8
23:31:54
40 2.7
23:32:09
40 2.6
23:32:24
40 2.9

我如何以这种方式操纵数据?我正试图将它变成一种我可以轻松绘制的形式。

3 个答案:

答案 0 :(得分:1)

这是一个awk解决方案,您可以根据自己的需要进行调整。

它实际上为每个时间戳/聚合生成一行,因为这通常更容易绘制。但是改变输出格式会很容易。

# file: aggregate.awk
#
# Call this as follows:
# awk -v columns=1,7 -f aggregate.awk data.file
BEGIN {
    ncols = split(columns, cols, /,/);
}
function print_line() {
    if (ts != "") {
        printf "%s", ts;
        for (i = 1; i <= ncols; ++i) printf " %f", data[i];
        printf "\n";
    }
}

/^..:..:../ {
    print_line();
    ts = $0;
    for (i = 1; i <= ncols; ++i) data[i] = 0;
    next;
}
    { for (i = 1; i <= ncols; ++i) data[i] += $(cols[i]); }
END { print_line(); }

示例:

$ awk -v columns=1,7 -f aggregate.awk <<EOF
23:31:39
20 0 24436 404 56 R 2.7 0.0 1:38.52
20 0 43064 20112 4484 R 0.8 0.1 0:00.12
20 0 27116 5152 3856 S 0.3 0.0 0:00.05
20 0 24952 4672 3708 S 0.0 0.0 0:00.05
23:31:54
20 0 24436 404 56 R 2.7 0.0 1:38.93
20 0 24952 4672 3708 S 0.0 0.0 0:00.05
23:32:09
20 0 24436 404 56 R 2.6 0.0 1:39.32
20 0 24952 4672 3708 S 0.0 0.0 0:00.05
23:32:24
20 0 24436 404 56 R 2.9 0.0 1:39.76
20 0 24952 4672 3708 S 0.0 0.0 0:00.05
EOF

23:31:39 80 3.8
23:31:54 40 2.7
23:32:09 40 2.6
23:32:24 40 2.9

答案 1 :(得分:1)

这是@rici答案的perl替代方法。请注意,数组索引从0开始,因此此示例数据使用的是0和6列,而不是1和7列。

#!/usr/bin/perl

use strict;

my @wanted_cols = (0,6);

my %sums;

while (<>) {
    my @cols = split /\s+/;
    if ($#cols) {
        foreach my $w (@wanted_cols) { $sums{$w} += $cols[$w] }
    } else {
        print join("\t", @sums{ @wanted_cols }), "\n";
        %sums = ();
        print $_;
    }
}
print join("\t", @sums{ @wanted_cols }), "\n";

答案 2 :(得分:0)

另一个awk

$ awk ' NF==1 { if(NR>1) print p,t1,t7 ;p=$0 ; t1=t7=0 } NF!=1 { t1+=$1;t7+=$7 } END { print p,t1,t7 }  ' mnot.txt
23:31:39 80 3.8
23:31:54 40 2.7
23:32:09 40 2.6
23:32:24 40 2.9
$