如何对具有多个条目的变量使用AWK命令?

时间:2016-10-11 19:44:57

标签: linux awk

如何使用awk从ID中获取具有各种观察/变量的信息。作为一个例子,我有两个ID(a,b)。两者都有不同年龄的6个观测值,并且测量值不同

根据ID和年龄对文件进行排序。 '行号'不是实际数据文件的一部分,但标题是!

我想使用awk识别并提取{print}"测量"每个唯一ID的最早年龄和最新年龄之间的差异。看下面的例子,对于ID(a),我想获得50-11 = 39。

    id age  measurement
1   a   2   11
2   a   4   20
3   a   6   19
4   a   7   89
5   a   8   43
6   a   12  50
7   b   1   15
8   b   3   23
9   b   5   30
10  b   6   33
11  b   7   45
12  b   10  60

如果您能详细解释我可以学习,我将非常感谢。

1 个答案:

答案 0 :(得分:2)

有序输入数据

鉴于行号不是数据的一部分而是标题,文件看起来更像:

id age  measurement
a   2   11
a   4   20
a   6   19
a   7   89
a   8   43
a   12  50
b   1   15
b   3   23
b   5   30
b   6   33
b   7   45
b   10  60

此脚本根据需要分析该文件:

awk 'NR==1    { next }
     $1 != id { if (id != "") print id, id_max - id_min; id = $1; id_min = $3; }
              { id_max = $3 }
     END      { if (id != "") print id, id_max - id_min; }' data

第一行会跳过文件的第一行。

第二行检查ID是否已更改;如果是,则检查是否存在旧ID,如果是,则打印数据。然后它存储当前ID并记录最小年龄的测量值。

第三行记录当前ID的当前最大年龄的度量。

如果文件中有任何数据,最后一行会打印出文件中最后一组的数据。

示例输出:

a 39
b 45

无序输入数据

即使数据未按ID和年龄排序,代码也可以适应工作:

awk 'NR==1  {   next }
            {   if (group[$1]++ == 0)
                {
                    order[++sequence] = $1
                    id_age_min[$1] = $2; id_val_min[$1] = $3
                    id_age_max[$1] = $2; id_val_max[$1] = $3
                }
                if ($2 < id_age_min[$1]) { id_age_min[$1] = $2; id_val_min[$1] = $3; }
                if ($2 > id_age_max[$1]) { id_age_max[$1] = $2; id_val_max[$1] = $3; }
            }
     END    {   for (i = 1; i <= sequence; i++)
                {
                    id = order[i];
                    print id, id_val_max[id] - id_val_min[id]
                }
            }' data

这会跳过标题行,然后在组到达时跟踪这些组,并安排按顺序打印数据(grouporder - 和sequence)。对于每一行,如果之前未见过该组,请设置当前行的数据(值均为最小值和最大值)。 如果当前行($2)中的年龄小于当前最小年龄(id_min_age[$1])的年龄,请记录新年龄和相应的值。如果当前行中的年龄大于当前最大年龄(id_max_age[$1])的年龄,请记录新年龄和相应的值。

最后,对于序列中的每个ID,打印出ID以及该ID的最大值和最小值之间的差异。

随机数据:

id age  measurement
a   12  50
b   10  60
a   4   20
b   3   23
b   5   30
a   7   89
b   6   33
b   7   45
a   8   43
a   6   19
a   2   11
b   1   15

示例输出:

a 39
b 45

恰好在a行之前出现b行,因此输出与以前相同。

更多数据(注意b此时出现a):

id age  measurement
b   10  60
a   12  50
a   4   20
b   3   23
c   2   19
d  -9   20
d  10   31
e  10   31
b   5   30
a   7   89
b   6   33
e  -9   20
b   7   45
a   8   43
a   6   19
f  -9   -3
f  -7   -1
g  -2   -8
g  -8   -3
a   2   11
b   1   15

结果:

b 45
a 39
c 0
d 11
e 11
f 2
g -5