如果我有以下文件:
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++)
集成到其中,它只打印第三条记录的值,而不是所有记录。
如果有必要澄清,请告诉我。
谢谢!
答案 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,您只需要使用相同的操作进行测试,但这次只需使用110000
,001100
,{{如果结果为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)两位)。