如何在awk中使用split和条件语句后打印字段?

时间:2015-11-15 22:32:34

标签: arrays awk

如果我有以下文件:

0|0 1|1 1|0
1|1 0|0 0|0
0|1 1|0 0|1
1|0 0|1 1|1

如何打印与NR==3 1相对应的字段,以便获得以下输出:

0 1 0
1 0 0
1 1 1
0 0 1

我试过了:

awk '{ split ($1, x, "|"); if ((NR==3) && (x[2]==1)) print x[2]; else if (NR==2) print x[1] }' input

此代码仅评估一个字段,因为我不确定如何将for (i=1;i<=NF;i++)集成到其中,它只打印第三条记录的值,而不是所有记录。

如果有必要澄清,请告诉我。

谢谢!

1 个答案:

答案 0 :(得分:1)

由于您需要第三行(作为关键行)来相互处理,您必须首先将所有行存储在一个数组中,一旦到达文件的末尾,就构建结果(在awk的END部分中)脚本)。

您可以使用按位运算符and来执行此操作。首先,您需要使用[ |]作为字段分隔符(空格或管道)。每行包含六个0或1,可以看作二进制数。

awk -F'[ |]' '{ a[NR] = $1*32 + $2*16 + $3*8 + $4*4 + $5*2 + $6 } # base10 conversion
  END {
      for(i=1;i<=NR;i++) {
          l=and(a[i], a[3]);
          print (and(l,48)?1:0)" "(and(l,12)?1:0)" "(and(l,3)?1:0);
      }
  }' file.txt

该脚本将每一行转换为整数并将其存储在数组中。 最后,使用and按位运算符,使用第三行处理每一行:

             Binary               Integer
line1:       0 0 1 1 1 0          13 
line3(key):  0 1 1 0 0 1          25
            -------------        ----
and:         0 0 1 0 0 0           8        (l)

在此操作之后,只有当前行和第三行(键行)中的位同时保留为1。

然后要知道您是否需要为两个字段的每组显示1或0,您只需要使用相同的操作进行测试,但这次只需使用110000001100,{{如果结果为null,则为1}}(即48,12,3):

000011

注意:您可以轻松更改脚本,使其适用于任意数量的字段。使用 Binary | Integer -------------------------------+------------------- l: 001000 001000 001000 | 8 8 8 110000 001100 000011 | 48 12 3 -------- -------- -------- | ---- ---- ---- and: 000000 001000 000000 | 0 8 0 not null: 0 1 0 | 0 1 0 循环进行行的base10转换并计算&#34;掩码&#34;需要(3,12,48,...)(例如,你可以在每个字段左侧移动3(11)两位)。