理解解开 fasta 文件的 awk 公式

Aga*_*the 3 awk bioinformatics

我刚刚找到了一个可用于解开 fasta 文件的公式。在给出公式之前,我需要解释一下什么是打开 fasta 文件。总之,fasta格式是这样的:

>name_of_sequence$
xxxxxxxxxxxxxxxxxxxxxx$
>name_of_sequence_2$
xxxxxxxxxxxxxxxxxxxxxx$
>name_of_sequence_3$
xxxxxxxxxxxxxxxxxxxxxx$
Run Code Online (Sandbox Code Playgroud)

这将是一个普通的 fasta 文件,因为我每个序列只有一行(xxxxxx ...)。美元符号是换行符。

但是,有时您可以找到这样的包装好的 fasta 文件:

>name_of_sequence$
xxxxxxxxx$
xxxxxxxxx$
xxxx$
>name_of_sequence_2$
xxxxxxxxx$
xxxxxxxxx$
xxxx$
>name_of_sequence_3$
xxxxxxxxx$
xxxxxxxxx$
xxxx$
Run Code Online (Sandbox Code Playgroud)

在这里,您仍然只有三个序列,但每个序列都分为三个部分。解开 fasta 文件意味着将后一种格式转换为前一种格式(每个序列一行)。

为此,您需要从后一个文件中删除换行符,但不是全部。您需要在序列名称之后保留换行符(例如:>name_of_sequence$)和在序列的末尾(例如:xxxx$)。

看来这个公式是这样做的:

cat infasta | awk '/^>/{print s? s"\n"$0:$0;s="";next}{s=s sprintf("%s",$0)}END{if(s)print s}' > outfasta
Run Code Online (Sandbox Code Playgroud)

我的问题是:有人可以向我解释它是如何工作的吗?

Kus*_*nda 5

这是你的awk脚本:

/^>/ {
    print s ? s "\n" $0 : $0;
    s = "";
    next;
}

{
    s = s sprintf("%s", $0);
}

END {
    if (s)
      print s;
}
Run Code Online (Sandbox Code Playgroud)

第一个块仅针对以 开头的行触发>,即 fasta 标题行。

在第一个块中,打印了一些东西。那东西是s ? s "\n" $0 : $0。这意味着“如果s非零(或未设置),则使用s并添加一个换行符,然后是整个当前行,否则只使用整个当前行”。在这个程序中,s将是一个属于最近处理过的头行的部分读取序列,当程序遇到一个头行时,这个print语句将输出最后一个序列(现在已经完成),如果有的话,后面跟着在新行上新发现的标题行。

然后块设置s为一个空字符串(我们还没有读取属于这个头的任何序列),我们跳到下一个输入行。

对所有输入行执行下一个块(但不针对标题行,因为由于next前一个块中的,这些将被跳过)。它只是将当前行附加到s. sprintf已使用,但我不太确定为什么(s = s $0也可能会起作用)。

在读取所有输入行后将执行最后一个块。它将打印属于最后一个标题行的序列,如果有的话。

概括:

awk脚本通过将它们保存在一个变量中来连接所有单独的序列行。当找到一个标题行时,它输出到目前为止读取的序列以及它自己的一行上的新标题。最后,输出属于最后一个头的序列。


awk不将序列存储在变量中的替代脚本(如果您的 fasta 文件中有非常大的基因组,则可能很有用):

/^>/ {
    if (NR == 1) {
        print;  # 1st header line, just print it.
    } else {
        # Print a newline for the prev. sequence, then the header line on its own line.
        printf("\n%s\n", $0);
    }
    next; # Skip to next input line.
}

{
    printf("%s", $0); # Print sequence without newline.
}

END {
    printf("\n"); # Add final newline to output.
}
Run Code Online (Sandbox Code Playgroud)

作为“单线”:

awk '/^>/{if(NR==1){print}else{printf("\n%s\n",$0)}next} {printf("%s",$0)} END{printf("\n")}' sequence.fasta
Run Code Online (Sandbox Code Playgroud)