如果行以">"开头,则使用 awk 查找模式,并在行尾添加模式的出现次数



我一直在努力使用 awk 找出一种方法来找到相同的模式,并在它们的末尾添加一个标签,显示它们在文件中存在的次数。 例如,如果Spiroplasma_culicicola出现 7 次,那么在第一次出现旁边,它应该写Spiroplasma_culicicola_1,在第二次出现旁边Spiroplasma_culicicola_2在第三次出现旁边写Spiroplasma_culicicola_3

等等等等但是我有一个看起来像这样的fasta文件:

>Spiroplasma_taiwanense
GKGVKYKNEKIIRKEGKAAGKMTTDVIADMLTRIRNANQRFHKEVVIPGSKVKLEIANIL
KKEGFIEDFKVADDFKKDITISLKYRGKTRVIKGLKRISKPGLRVYSHATEIPQVLNGLG
IAIVSTSHGIMTDKEARQQNAGGEVLAFVW
>Spiroplasma_diminutum
NRLEKQYKEKIVPELFKEKQYKSIMQVPKITKVVINMGIGDAVQDTKKLDDAVLELQQIT
GQKPLVTKAKKSLAVFKLREGMPIGAKVTLRGKRMYEFLDKLISVALPRVRDFRGVPKTS
FDKQGNYTMGIKEQIIFPEIDYDKVKKVRGMDITIVTTANQKDEAFSLLQKMGMPFVKMN
KSKILRGDVVKVIAGSHKGKIGPVVKLSKDKKRVYVEGIVAIK-HAKPSQTDQEGGIREI
PAGVDISNVSLVDPKVKDSATRVGYKIADGKKVRIAKKSGSEVK-MIQNESRLKVADNSG
>Spiroplasma_diminutum
NRLEKQYKEKIVPELFKEKQYKSIMQVPKITKVVINMGIGDAVQDTKKLDDAVLELQQIT
GQKPLVTKAKKSLAVFKLREGMPIGAKVTLRGKRMYEFLDKLISVALPRVRDFRGVPKTS
FDKQGNYTMGIKEQIIFPEIDYDKVKKVRGMDITIVTTANQKDEAFSLLQKMGMPFVKMN
...

所以我想添加"标签",即仅在标题旁边显示出现的数字! 因此,上面的文件应如下所示:

>Spiroplasma_taiwanense_1
GKGVKYKNEKIIRKEGKAAGKMTTDVIADMLTRIRNANQRFHKEVVIPGSKVKLEIANIL
KKEGFIEDFKVADDFKKDITISLKYRGKTRVIKGLKRISKPGLRVYSHATEIPQVLNGLG
IAIVSTSHGIMTDKEARQQNAGGEVLAFVW
>Spiroplasma_diminutum_1
NRLEKQYKEKIVPELFKEKQYKSIMQVPKITKVVINMGIGDAVQDTKKLDDAVLELQQIT
GQKPLVTKAKKSLAVFKLREGMPIGAKVTLRGKRMYEFLDKLISVALPRVRDFRGVPKTS
FDKQGNYTMGIKEQIIFPEIDYDKVKKVRGMDITIVTTANQKDEAFSLLQKMGMPFVKMN
KSKILRGDVVKVIAGSHKGKIGPVVKLSKDKKRVYVEGIVAIK-HAKPSQTDQEGGIREI
PAGVDISNVSLVDPKVKDSATRVGYKIADGKKVRIAKKSGSEVK-MIQNESRLKVADNSG
>Spiroplasma_diminutum_2
NRLEKQYKEKIVPELFKEKQYKSIMQVPKITKVVINMGIGDAVQDTKKLDDAVLELQQIT
GQKPLVTKAKKSLAVFKLREGMPIGAKVTLRGKRMYEFLDKLISVALPRVRDFRGVPKTS
FDKQGNYTMGIKEQIIFPEIDYDKVKKVRGMDITIVTTANQKDEAFSLLQKMGMPFVKMN
...

根据之前回答的问题,我认为我应该使用 awk,如下所示: awk '$1 ~/^>/{gsub(" ", ", $0);a[$0]++;打印 $0"_"a[$0]}'

(从这里窃取的代码:找到出现次数并将其添加到模式旁边)

但是我找不到保存文件中更改的方法(例如,像 -i 的 sed),并且我无法将其重定向到新文件,因为它只是打印/保存标题。

有什么想法吗?

谢谢 P

似乎问题在于您不理解在其他地方找到的代码:

awk '$1 ~ /^>/ {gsub(" ", "", $0); a[$0]++; print $0"_"a[$0]}'

从外观上看,它执行您想要的替换并打印以>开头的行。

因此,缺少的部分是打印其余行而不进行任何修改。

你可以这样做:

awk '$1 ~ /^>/ { gsub(" ", "", $0); a[$0]++; $0 = $0"_"a[$0] } { print }'

也就是说,将print更改为第一个块中的赋值,并添加一个无条件的第二个块,该块始终打印所有内容。

通过将增量与赋值相结合,并将{ print }更改为通用速记(只是默认操作的1条件,打印),可以进一步简化代码。

如注释中所述,可以通过传递正则表达式文本作为第一个参数来改进对gsub的调用,而不是在使用前必须转换为正则表达式的字符串。也可以通过删除最后一个参数$0(默认值)来缩短它。

awk '$1 ~ /^>/ { gsub(/ /, ""); $0 = $0 "_" ++a[$0] } 1'

要覆盖原始文件,只需重定向到临时文件,然后覆盖原始文件:

awk '...' input > tmp && mv tmp input

或者使用 GNU awk,如评论中所述:

awk -i inplace '...' input