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

Nam*_*ata 3 bash awk

我想使用五个字段(第 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
Run Code Online (Sandbox Code Playgroud)

文件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
Run Code Online (Sandbox Code Playgroud)

输出:

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
Run Code Online (Sandbox Code Playgroud)

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

slm*_*slm 5

这是一个仅使用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
}
Run Code Online (Sandbox Code Playgroud)

然后用上面的2个文件像这样运行它:

$ awk -f ex.awk file1 file2
Run Code Online (Sandbox Code Playgroud)

例子

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
Run Code Online (Sandbox Code Playgroud)

需求变化

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

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

s2/40   40      .       S       S       90      N=2     F=5;U=4
Run Code Online (Sandbox Code Playgroud)

添加到原始解决方案的单行可以解决需求中的这种特殊变化。

if ((k in a) && (lc==$4) && (ld==$5)) next
Run Code Online (Sandbox Code Playgroud)

新例子

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
}
Run Code Online (Sandbox Code Playgroud)

重新运行新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
Run Code Online (Sandbox Code Playgroud)