在 AWK 中,根据第一列内容分隔字段,在第二列中匹配,在第四列中减去值

  • 本文关键字:二列 四列 AWK 一列 分隔 字段 awk
  • 更新时间 :
  • 英文 :


我的输入文件是这样的:

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 循环逐步通过数组,因此不能保证输出与输入的顺序相同。

最新更新