使用 awk 进行多列匹配和调整

使用 awk 进行多列匹配和调整

我有一个看起来像这样的文件

    ID A1 A2 A3
    1  A  G  A
    2  T  G  A
    3  T  A  G
    4  T  G  A
    5  A  A  G
    6  A  C  A
    7  C  T  G

它有数千行长,由 G、C、T、A 组成,其中 G 补充 C,A 补充 T。我想做的是在 A2 或 A3 中搜索 A1 的匹配项。如果存在匹配,则将其保留原样,如果不存在,则将 A2 和 A3 更改为它们的补码,即 A=T 和 G=C,反之亦然。

所以输出将是:

    ID A1 A2 A3
    1  A  G  A
    2  T  C  T
    3  T  T  C
    4  T  C  T
    5  A  A  G
    6  A  C  A
    7  C  A  C

我想我可以通过使用 awk 来过滤匹配和不匹配的 ID:

   awk '{if($2 != $3 || $2 != $4) print $0}' mergedlist > nonmatchlist

   awk '{if($2 == $3 || $2 == $4) print $0}' mergedlist > matchlist

但它只适用于一个变量,即前者的 T 和后者的 A。

答案1

perl -lane 'sub flip { if ($_[0] eq "T") { "A" } elsif ($_[0] eq "A") { "T" } elsif ($_[0] eq "G") { "C" } elsif ($_[0] eq "C") { "G" } else { $_[0] } } if (!($F[1] eq $F[2] or $F[1] eq $F[3])) { $F[2] = flip($F[2]); $F[3] = flip($F[3]) } print "@F"' < input

应该很容易移植回来,awk因为它并没有真正做任何花哨的事情,但这需要我更多的时间来弄清楚。

答案2

你可以构造一个关联数组作为补集的查找表,例如

awk '
  BEGIN {
    complement["A"]="T"; complement["T"]="A";
    complement["C"]="G"; complement["G"]="C";
  } 

  NR>1 && $3!=$2 && $4!=$2 {
    $3 = complement[$3]; 
    $4 = complement[$4];
  } 

  {
    print;
  }
' file

答案3

除了 @steeldriver 建议的数组之外,您还可以定义一个函数:

awk '
  BEGIN { FS == " +" }
  NR == 1 {print $0 }
  function CHANGE( F )
    {
      if ( F == "A" ) F = "T"
      else if ( F == "T" ) F = "A"
      else if ( F == "C" ) F = "G"
      else F = "C"
      return F
    }
  NR >= 2 {
    if ( $2 == $3 || $2 == $4 ) print $0
    else {
      $3=CHANGE($3)
      $4=CHANGE($4)
      printf "%5d%3s%3s%3s\n",$1,$2,$3,$4
    }
  }
' file 

相关内容