awk:在多列中查找重复的字段,在条件下打印新列

时间:2018-09-11 11:47:06

标签: awk

我需要您的awk帮助。 我正在尝试查找在文件中复制了列$1$2的行,并且其中至少有一个副本在列ref中具有值$3的行。如果是这样,请在新列中打印"1"其他打印"2"

输入文件的示例为:

a       123     exp_a
a       123     ref
b       146     exp_a
c       156     ref
d       205     exp_a
d       205     exp_b

输出文件将是:

a       123     exp_a     1
a       123     ref       1
b       146     exp_a     2
c       156     ref       2
d       205     exp_a     2
d       205     exp_b     2

在这里,a 123与在ref处有$3的一行重复,因此得到1。相比之下,其他人要么不在$1$2复制,要么在ref没有$3,所以得到2

经过一番摆弄之后,我设法将1$1重复的行放在$2上,但是{{1} },我无法告诉awk打印ref,否则... SPOILERS:我的代码可能非常难看。

$3

我得到的输出是:

2

3 个答案:

答案 0 :(得分:2)

请您尝试以下。

awk 'FNR==NR{a[$1,$2]++;b[$1,$2]=$3;next} {$NF=(b[$1,$2]=="ref" && a[$1,$2]>1?$NF OFS "1":$NF OFS "2")} 1' OFS="\t"  Input_file  Input_file

在这里也添加非单一衬里形式的解决方案。

awk '
FNR==NR{
  a[$1,$2]++
  b[$1,$2]=$3
  next
}
{
  $NF=(b[$1,$2]=="ref" && a[$1,$2]>1?$NF OFS "1":$NF OFS "2")
}
1
' OFS="\t" Input_file Input_file

答案 1 :(得分:2)

$ cat tst.awk
BEGIN { OFS="\t" }
NR==FNR {
    cnt2[$1,$2]++
    cnt3[$1,$2,$3]++
    next
}
{ print $0, (cnt2[$1,$2]>1 && cnt3[$1,$2,"ref"]>0 ? 1 : 2) }

$ awk -f tst.awk file file
a       123     exp_a   1
a       123     ref     1
b       146     exp_a   2
c       156     ref     2
d       205     exp_a   2
d       205     exp_b   2

答案 2 :(得分:0)

该数据仅用一次即可处理,但是希望文件由“ {key}” $1 $2排序。每个“键”组中的记录以随机顺序(for(i in a))输出:

awk '
BEGIN { FS=OFS="\t" }
{
    if((p!=$1 OFS $2) && NR>1) {            # when the $1 $2 changes from previous
        for(i=1;i<=a[0];i++) {              # iterate and output buffered records
            print p,a[i],2-(a[-1]&&a[0]>1)  # more than one record in buffer and ...
        }                                   # ... ref for $4=1
        delete a                            # empty buffer after output
    }
    if($3=="ref")                           # if there is a match in $3
        a[-1]++                             # increase counter
    a[++a[0]]=$3                            # buffer records to a, a[0] counter
    p=$1 OFS $2                             # p is for previous "key"
}
END {
    for(i=1;i<=a[0];i++)                    # duplicate code from above if
        print p,a[i],2-(a[-1]&&a[0]>1)
}' file

输出:

a       123     exp_a   1
a       123     ref     1
b       146     exp_a   2
c       156     ref     2
d       205     exp_a   2
d       205     exp_b   2

记录计数器a[0]和引用计数器a[-1]位于a[]中,以单个delete a对其进行重置。