我的输入文件是这样的:
a10 otu1 xx 44
b24 otu2 xxx 52
x35 otu3 xy 11
x45 otu3 zz 22
z452 Otu5 rr 78
control1 otu1 w 4
control2 otu2 ee 30
control3 otu3 tt 20
control4 otu4 yy 10
首先,我想将控件与第 1 列中的其他控件分开,然后匹配第二列 其他第二列的控制值。在第二列中找到匹配的位置,我想要 减去第四列中的相应值。
输出文件将是:
a10 otu1 xx 40
b24 otu2 xxx 22
x35 otu3 xy -9
x45 otu4 zz 12
z452 Otu5 rr 78
现在,为了匹配第二列并减去第四列中的值,我使用:
awk 'NR==FNR {a[$2]=$2 in a?a[$2]-$4:$4; next} !b[$2]++ {print $1,$2,$3,a[$2]}' inputfile.txt{,}
如何在脚本中提供单独的字段信息(控件与其他字段(?
你能试试下面的吗?
awk '
!/^control/{
a[++count1]=$NF
b[count1]=$1 OFS $2 OFS $3
next
}
{
c[++count2]=$NF
}
END{
for(i=1;i<=count1;i++){
print b[i],a[i]-c[i]
}
}
' Input_file
更通用的解决方案:如果您不想在第一个数组 a 中硬编码字段值,并且第一个文件中有超过 4 个字段,请尝试以下操作。
awk '
!/^control/{
a[++count1]=$NF
$NF=""
sub(/ +$/,"")
b[count1]=$0
next
}
{
c[++count2]=$NF
}
END{
for(i=1;i<=count1;i++){
print b[i],a[i]-c[i]
}
}
' Input_file
$ cat tst.awk
NR==FNR {
if ( /^control/ ) {
control[$2] = $NF
}
next
}
!/^control/ {
$NF = $NF - control[$2]
print
}
$ awk -f tst.awk file file
a10 otu1 xx 40
b24 otu2 xxx 22
x35 otu3 xy -9
x45 otu3 zz 2
z452 Otu5 rr 78
这是对此的另一种看法:
/^control/ {
a[$2]=a[$2]-$4
next
}
{
a[$2]=a[$2]+$4
b[$2]=$1 OFS $2 OFS $3
}
END {
for(i in b) print b[i] OFS a[i]
}
这会减去control
行上的任何值,将其他行上的任何值相加,并将它们存储在数组a[]
中。它维护一系列行内容,b[]
.
通过在数组中存储内容,可能会有多个数据或控制行影响该值,并且它们可以以任何顺序出现在您的输入中(因为 44 - 40 与 -40 + 44 相同(。
请注意,由于我们的 END for 循环逐步通过数组,因此不能保证输出与输入的顺序相同。