使用 Awk 和 Bash 比较基于 5 个字段的文件

使用 Awk 和 Bash 比较基于 5 个字段的文件

我想使用五个字段(第 1、2、4、5、6 列)比较 File1 和 File2(以空格分隔)。

*逻辑:*如果 File1 和 File2 的第 1 列和第 2 列完全匹配,并且 File2 具有与 file1 第 4 列和第 5 列中存在的任何字符相同的字符,则 file1 和 file2 的这些行将连接并重定向为输出。

文件1:

s2/80   20      .       A       T       86      N=2     F=5;U=4
s2/20   10      .       G       T       90      N=2     F=5;U=4
s2/90   60      .       C       G       30      N=2     F=5;U=4

文件2:

s2/90   60      .       G       G       97      N=2     F=5;U=4
s2/80   20      .       A       A       20      N=2     F=5;U=4
s2/15   11      .       A       A       22      N=2     F=5;U=4
s2/90   21      .       C       C       82      N=2     F=5;U=4
s2/20   10      .       G       G       99      N=2     F=5;U=4
s2/80   10      .       T       G       11      N=2     F=5;U=4
s2/90   60      .       G       T       55      N=2     F=5;U=4

输出:

s2/80  20 . A   T   86  N=2 F=5;U=4  s2/80  20  . A   A   20   N=2     F=5;U=4
s2/20  10 . G   T   90  N=2 F=5;U=4  s2/20  10  . G   G   99   N=2     F=5;U=4
s2/90  60 . C   G   30  N=2 F=5;U=4  s2/90  60  . G   G   97   N=2     F=5;U=4

我是这个领域的新手,希望得到任何指导。

答案1

这是一个仅使用awk.将以下代码放入名为的文件中ex.awk

BEGIN{}
FNR==NR{
    k=$1" "$2
    a[k]=$4" "$5
    b[k]=$0
    c[k]=$4
    d[k]=$5
    next
}

{ k=$1" "$2
  lc=c[k]
  ld=d[k]
  # file1 file2
  if ((k in a) && ($4==$5) && (lc==$4) || (ld==$5)) print b[k]" "$0
}

然后使用上面的两个文件运行它:

$ awk -f ex.awk file1 file2

例子

sed只是为了格式化 StackExchange 的输出!

$ awk -f ex.awk file1 file2 | sed 's/[ ]\+/  /g'
s2/90  60  .  C  G  30  N=2  F=5;U=4  s2/90  60  .  G  G  97  N=2  F=5;U=4
s2/80  20  .  A  T  86  N=2  F=5;U=4  s2/80  20  .  A  A  20  N=2  F=5;U=4
s2/20  10  .  G  T  90  N=2  F=5;U=4  s2/20  10  .  G  G  99  N=2  F=5;U=4

要求的变化

OP 在下面的评论中提到,他希望最终的解决方案能够删除其中第 4 列和第 5 列与 中的file1第 4 列和第 5 列相匹配的任何行file2

例如,将此行添加到file1& file2

s2/40   40      .       S       S       90      N=2     F=5;U=4

在原始解决方案中添加一行即可解决需求中的这一特定变化。

if ((k in a) && (lc==$4) && (ld==$5)) next

新例子

ex2.awk:

BEGIN{}
FNR==NR{
  k=$1" "$2
  a[k]=$4" "$5
  b[k]=$0
  c[k]=$4
  d[k]=$5
  next
}

{ k=$1" "$2
  lc=c[k]
  ld=d[k]
  if ((k in a) && (lc==$4) && (ld==$5)) next
  if ((k in a) && ($4==$5) && (lc==$4) || (ld==$5)) print b[k]" "$0
}

重新运行新awk脚本ex2.awk

$ awk -f ex2.awk file1 file2 | sed 's/[ ]\+/  /g'
s2/90  60  .  C  G  30  N=2  F=5;U=4  s2/90  60  .  G  G  97  N=2  F=5;U=4
s2/80  20  .  A  T  86  N=2  F=5;U=4  s2/80  20  .  A  A  20  N=2  F=5;U=4
s2/20  10  .  G  T  90  N=2  F=5;U=4  s2/20  10  .  G  G  99  N=2  F=5;U=4

相关内容