匹配字段中的值并根据匹配为其分配身份

匹配字段中的值并根据匹配为其分配身份
chr:pos1:pos2   Sun     NC      S1      S2      S3      S4      S9      S11     S14     S15     S16     S17     S18     S19     S28     S29     S30     S33     S34     S35     S36     S37     S38     S39
Aradu.A01:100145549:100145556   AG      AA      AA      AA      AA      AA      AA      AA      AA      AA      AA      AA      AA      AA      AA      AA      AA      AA      AA      AA      AA      AA
Aradu.A01:100408119:100408137   CA      TA      0       0       0       TA      TA      TA      TA      TA      TA      TA      TA      TA      TA      TA      TA      TA      TA      TA      TA      0
Aradu.A01:10102206:10102212     TG      TA      TA      TA      TA      0       TG      TA      TA      TA      TG      TG      TG      TG      TG      TA      TG      TG      TA      0       TG      TG
Aradu.A01:10112010:10112029     GA      GG      GG      GG      GG      GG      GA      GG      GG      GG      GA      0       GA      GA      GA      GG      GA      GA      GG      GA      0       GA
Aradu.A01:10112029:10112059     AC      GC      GC      GC      GC      GC      AC      GC      GC      GC      AC      0       AC      AC      AC      GC      AC      0       GC      AC      0       AC
Aradu.A01:101198026:101198058   GT      GC      GC      GC      GT      GC      0       GT      GT      GC      GT      GT      GT      0       GT      GC      GT      GC      GC      GT      0       GT
Aradu.A01:101198058:101198081   TC      CC      CC      CC      TC      CC      0       TC      TC      CC      TC      TC      TC      0       TC      CC      TC      CC      CC      TC      0       TC
Aradu.A01:101306922:101306946   AG      AA      AA      AA      AG      0       AA      AG      AG      AA      0       AG      AG      AG      AG      AA      AG      AG      AA      AG      AG      AG

在给定的文件中,我尝试将第 4 列及以后的所有字段中的值与第 2 列和第 3 列相匹配。如果字段(第 4 列及以后)的值与第 2 列字段匹配,则将其标记为 S(如果匹配)与 col 3 然后将其标记为 N,如果它是 0,则将其分配为 -1。

以下是我尝试过的:

NR>1  {for(i=4;i<=NF;i++)
        { if ( $i == $2 ) $i=S ;
          if ( $i == $3 ) $i=N ;
          if ( $i == 0 ) $i=-1 ;
       } ## if ;
       ## for loop is done
       print ;
       }

这会导致将除前 3 个字段之外的所有字段分配为 -1。

答案1

这似乎可以解决问题:

NR > 1 {
  for( i=4; i<NF; i++) {
    if( $i == $2 ) {
      $i = "S"
    }
    else if( $i == $3 ) {
      $i = "N"
    }
    else if( $i == 0 ) {
      $i = -1
    }
  }
  print
}

将其放入名为 eg 的文件中363142.awk,然后运行:

$ awk -f 363142.awk /path/to/input

答案2

perl -F\\s+ -pale '
   $. > 1 and /(?:\S+\s+){3}/g and
   s{\G(\S+)(\s*)}
   {
      ($1 eq $F[1] ? "S" : $1 eq $F[2] ? "N" : $1 eq "0" ? -1 : $1) . $2
   }cge;
' your_genes_file

选项

  • -F\\s+将设置FS为一个或多个空格=>/\s+/
  • -p将设置一个隐式文件循环读取并且打印是自动的。
  • -a将根据-F选项提供的字段分割分隔符或默认的单个空格重新分割每条记录。这些字段存储在数组中@F
  • -l将设置ORS=RS=\n
  • -ePerl要应用于每条记录的代码。

解释

我们跳过处理的第一行。-p选项将小心打印它。然后我们将正则表达式引擎标记停放在第四个字段的开头,因为那是所有操作应该开始的地方。然后我们在、、 和模式下应用该s///命令。=> 正则表达式标记将从最后一个命令中停放的位置开始,而不是从开头开始。=> 将查看整行以对其进行转换,并将替换部分视为要执行的代码,其结果将停放在替换部分中。globalcumulativeeval/cm//g/g/es//repl/Perl

GNU sed

可以将其写入,POSIX sed但这样代码会妨碍清晰度,因此只能作为适度的练习。

sed -e '
   1b

   # fence the column 2 and go looking for col2 matching fields from col 4 onwards
   s/\S\+/\n&\n/2
   :c2
   s/\(\n\(.*\)\n\s\+\S\+\s.*\)\<\2\>/\1S/g;tc2
   s/\n//g

   # fence the column 3 and go looking for col3 matching fields from col 4 onwards
   s/\S\+/\n&\n/3
   :c3
   s/\(\n\(.*\)\n.*\)\<\2\>/\1N/g;tc3
   s/\n//

   # from col 4 onwards look for any lone 0s and change them to -1
   :zm1
   s/\(\n.*\)\<0\>/\1-1/;tzm1
   s/\n//

' gene_file.dat

珀尔

在这里,我们删除任何会干扰 @F 数组索引的前导空格,然后在打印数据时恢复它。我们map将元素 6 向前(空格为 4+2)并检查它们是否等于第 2/3 列或 0。

perl -F'(\s+)' -lane '
   print,next if $. == 1;
   my $dummy = splice @F, 0, 2 if /^\h/;
   print $dummy, @F[0..5], map {
      s/^\Q$F[2]\E$/S/ or s/^\Q$F[4]\E$/N/ or s/^0$/-1/; $_
   } @F[6 .. $#F];
' gene_file.dat

相关内容