Bash:嵌套 while 循环来检测重复项并对重复项进行编号

Bash:嵌套 while 循环来检测重复项并对重复项进行编号

所以我有一个带有基因标题的文本文件,并且同一物种下有不同的基因序列。因此,我提取了标头 (headers.txt) 并将其复制到另一个文件 ( uniqueheaders.txt) 中。我删除了 中的所有重复项uniqueheaders.txt

我正在尝试循环读取一行,uniqueheaders.txt然后循环读取headers.txt以检查重复项。该if语句检测重复项并增加计数器以将其附加到标头。这将对所有标头进行编号,headers.txt以便我将它们插回我的 FASTA 文件中。我的代码在这里:

while IFS= read -r uniqueline
do
    counter=0
    while IFS= read headline
    do
        if [ "$uniqueline" == "$headline" ]
        then
            let "counter++"
            #append counter to the headline variable to number it.
            sed "$headline s/$/$counter/" -i headers
        if
    done < headers.txt
done < uniqueheaders.txt

问题是终端不断吐出错误

sed: -e expression #1, char 1: unknown command: 'M'

sed: -e expression #1, char 2: extra characters after command

这两个文件都包含唯一的标头名称:

Mus musculus
Homo sapiens
Rattus norvegicus

如何修改sed命令来防止此错误?有更好的方法吗bash

输入示例(请注意,基因序列实际上并没有占用多少行的模式)**** 基因序列全部位于一个文件中

Mus musculus 
MDFJSGHDFSBGKJBDFSGKJBDFS
NGBJDFSBGKJDFSHNGKJDFSGHG
Rattus norvegicus
SNOFBDSFNLSFSFSFSJFJSDFSD
Mus musculus
NJALDJASJDLAJSJAPOJPOASDJG
DSFHBDSFHSDFHDFSHJDFSJKSSF

期望的输出:

Mus musculus1 
MDFJSGHDFSBGKJBDFSGKJBDFS
NGBJDFSBGKJDFSHNGKJDFSGHG
Rattus norvegicus
SNOFBDSFNLSFSFSFSJFJSDFSD
Mus musculus2
NJALDJASJDLAJSJAPOJPOASDJG
DSFHBDSFHSDFHDFSHJDFSJKSSF

答案1

awk我想到了一个基于基础的解决方案。

由于您的头文件没有任何特定的标识,因此我们将采用“双文件双遍”方法,其中首先读取包含唯一标头的头文件,然后读取实际的序列文件两次,以便打印仅对那些出现多次的标头进行消歧编号:

awk 'NR==FNR{tot[$0]=0;next}
     !final {if ($0 in tot) {tot[$0]++};next}
      final && ($0 in tot) {if (tot[$0]>1) $0=$0 (++cnt[$0])}1' uniqueheaders.txt sequence.txt final="1" sequence.txt 
  • 如果NR全局行计数器等于FNR每个文件的行计数器,我们就知道我们处于第一个要处理的文件(此处uniqueheaders.txt)。然后,我们只需将标题“记录”在一个数组中tot,该数组稍后将保存标题出现的总次数。
  • 由于我们不知道有多少标题行和序列文件行,因此行计数器变量将无法帮助我们进一步识别我们所在的文件(至少如果我们不想依赖任何特定的awk实现) 。由于我们必须处理“序列文件”(您的示例输入)两次,以便禁止1为那些仅出现一次的标头附加 a (请参阅此问答供讨论),我们将把它作为 的参数声明两次,但为第二遍awk设置一个标志。final
  • 在序列文件的第一遍(final尚未设置)中,我们只查看包含标题的那些行(即$0整行位于数组的索引中tot)并增加总出现次数计数器。
  • 在序列文件的第二遍中(final现在设置为1),我们通常打印所有行,但在作为标题行的那些行上(再次,通过$0数组的索引来指示tot),我们附加一个计数器(存储在数组中)cnt),如果我们知道此标头有重复项 ( tot[$0]>1)。

笔记如果序列文件的标题行可以通过某种标准挑选出来(例如,所有基因序列都用空行分隔),那么我们就不需要外部文件,并且可以在一次调用uniqueheaders.txt中完成这一切。awk

相关内容