如果与另一个 file.txt 匹配,则替换文件 (fasta) 中的 header

replace header in a file (fasta) if match with another file.txt

我有一个文件 Pseudo.fasta 看起来像这样

>Pseudomonas_brassicacearum_51MFCVI2.1_ABFDHLDI_02438
AATCGCAATTTGCCCAAA
>Pseudomonas_brassicacearum_51MFCVI2.1_ABFDHLDI_03705
GATCCTTAACGGA
>Pseudomonas_brassicacearum_PP1_210F_EGEGDKLG_01471
AGGCCTTAAACCTT

和另一个 file.txt 有两列:1 列与 .fasta 文件的 header 部分匹配,第二列和文件看起来像这样。

Pseudomonas_brassicacearum_51MFCVI2.1   JW5VryPcbM
Pseudomonas_brassicacearum_51MFCVI2.1   JW5VryPcbM
Pseudomonas_brassicacearum_PP1_210F     nxUvzhi39L

基本上,如果第一个文件的第一列与 fasta header.[=17 匹配(第一部分),我想用第二个文件的第二列替换 header =]

deisred 输出应该如下所示

>JW5VryPcbM_1
AATCGCAATTTGCCCAAA
>JW5VryPcbM_2
GATCCTTAACGGA
>nxUvzhi39L_1
AGGCCTTAAACCTT

我正试图用 awk 做到这一点

awk -F "\t" 'FNR==NR {f2[]=;next}  in f2 {=f2[]}1' file.txt FS='>' OFS='>' Pseudomo.fasta 

但此解决方案仅在要匹配的字符串完全相同时才有效。

在此之后,我将应用此 awk 行添加一个数字,以防 headers

中出现重复项
awk '{print [=16=] (/^>/ ? "_" (++c[]) : "")}' Pseudo.fasta

也许直接用上一个命令通过管道传递最后一个也很酷。 有什么建议吗? 谢谢!

你可以使用这个awk:

awk '
NR == FNR {
   map[">" ] = 
   next
}
sub(/(_[^_]+){2}$/, "") && [=10=] in map {
   [=10=] = ">" map[[=10=]] "_" ++freq[map[[=10=]]]
} 1' file.txt Pseudo.fasta

>JW5VryPcbM_1
AATCGCAATTTGCCCAAA
>JW5VryPcbM_2
GATCCTTAACGGA
>nxUvzhi39L_1
AGGCCTTAAACCTT

其他fasta相关问题偶尔会在header行显示其他文字;修改 OP 示例输入的第一行以演示:

$ cat Pseudo.fasta
>Pseudomonas_brassicacearum_51MFCVI2.1_ABFDHLDI_02438 keep the rest of this text
AATCGCAATTTGCCCAAA
>Pseudomonas_brassicacearum_51MFCVI2.1_ABFDHLDI_03705
GATCCTTAACGGA
>Pseudomonas_brassicacearum_PP1_210F_EGEGDKLG_01471
AGGCCTTAAACCTT

如果 objective 仅替换 header 记录中的第一个(space 分隔)字段,同时保留其他文本,一个 awk 想法:

awk '
FNR==NR { a[]=; next }
/^>/    { gene=substr(,2)
          for (i in a)
              if (gene ~ i) { =">" a[i] "_" ++cnt[i]; break }
        }
1
' replacements.txt Pseudo.fasta

注意: 如果 header 记录的字段由非白色 space 分隔的字段(例如竖线、分号),则进行一些小的编辑可以使此代码可以使用不同的定界符

这会生成:

>JW5VryPcbM_1 keep the rest of this text
AATCGCAATTTGCCCAAA
>JW5VryPcbM_2
GATCCTTAACGGA
>nxUvzhi39L_1
AGGCCTTAAACCTT

在您的代码中,您使用 in f2 检查密钥,但您需要部分匹配。

要获得部分匹配,您可以循环您正在使用的数组 f2,然后例如使用带有 index() 的另一个变体,并在部分匹配时直接打印。

然后使用next转到下一条记录。

如果不匹配,最后的}1中的1会默认打印该行

awk '
FNR==NR {f2[]=;next}
/^>/ {
  for (i in f2) {
    if (index(substr(,2), i)) {
      print ">"f2[i]; next
    }
  }
}1' file.txt Pseudo.fasta 

输出

>JW5VryPcbM
AATCGCAATTTGCCCAAA
>JW5VryPcbM
GATCCTTAACGGA
>nxUvzhi39L
AGGCCTTAAACCTT