11

我有一个 fasta 文件,其中的序列用换行符分解。我想删除换行符。这是我的文件的示例:

>accession1
ATGGCCCATG
GGATCCTAGC
>accession2
GATATCCATG
AAACGGCTTA

我想把它转换成这个:

>accession1
ATGGCCCATGGGATCCTAGC
>accession2
GATATCCATGAAACGGCTTA

我在这个网站上找到了一个潜在的解决方案,如下所示:

cat input.fasta | awk '{if (substr($0,1,1)==">"){if (p){print "\n";} print $0} else printf("%s",$0);p++;}END{print "\n"}' > joinedlineoutput.fasta

但是,这会在每个条目之间放置一个额外的换行符,因此文件如下所示:

>accession1
ATGGCCCATGGGATCCTAGC

>accession2
GATATCCATGAAACGGCTTA

我是个 awk 菜鸟,但我尝试修改命令。我的猜测是if (p){print "\n";}罪魁祸首......可能print "\n"是添加两个换行符。我不知道如何只添加一个换行符……这可能很容易,但就像我说的,我是个菜鸟。这是我的(不成功的)解决方案:

awk '{if (substr($0,1,1)==">"){print "\n"$0} else printf("%s",$0);p++;}END{print "\n"}' input.fasta > joinedoutput.fasta

但是,这会在文件的开头添加一个空行,因为它总是在打印第一个入藏号之前打印一个新行:

{empty line} 
>accession1
ATGGCCCATGGGATCCTAGC
>accession2
GATATCCATGAAACGGCTTA

任何人都有解决方案以正确格式获取我的文件?谢谢!

4

9 回答 9

13

这个awk程序:

% awk '!/^>/ { printf "%s", $0; n = "\n" } 
/^>/ { print n $0; n = "" }
END { printf "%s", n }
' input.fasta

将产生:

>accession1
ATGGCCCATGGGATCCTAGC
>accession2
GATATCCATGAAACGGCTTA

解释:

在不以 a 开头的行上>,打印没有换行符的行并存储换行符(在变量中n)以备后用。

在以 开头的行上>,打印存储的换行符(如果有)和行。重置n,以防这是最后一行。

如果需要,以换行符结尾。

笔记:

默认情况下,变量被初始化为空字符串。不需要在中显式“初始化”一个变量,这是您在和大多数其他传统语言中所做的。

-- 6.1.3.1 在程序中使用变量GNU Awk 用户指南

于 2013-04-06T23:22:16.797 回答
9

公认的解决方案很好,但它并不是特别 AWKish。考虑改用这个:

 awk '/^>/ { print (NR==1 ? "" : RS) $0; next } { printf "%s", $0 } END { printf RS }' file

解释:

对于以 开头>的行,打印该行。如果该行不是文件中的第一行,则使用三元运算符打印前导换行符。对于不以 开头>的行,打印没有尾随换行符的行。由于文件中的最后一行不会以 开头>,因此请使用该END块打印最后一个换行符。

请注意,通过设置空输出记录分隔符、启用默认打印和重新分配以>. 尝试:

awk -v ORS= '/^>/ { $0 = (NR==1 ? "" : RS) $0 RS } END { printf RS }1' file
于 2015-01-14T10:36:43.537 回答
4

还有另一种 awk 单线,应该适用于您的情况。

awk '/^>/{print s? s"\n"$0:$0;s="";next}{s=s sprintf("%s",$0)}END{if(s)print s}' file
于 2013-04-06T23:45:06.947 回答
4

我会用sed这个。使用GNU sed

sed ':a; $!N; /^>/!s/\n\([^>]\)/\1/; ta; P; D' file

结果:

>accession1
ATGGCCCATGGGATCCTAGC
>accession2
GATATCCATGAAACGGCTTA

解释:

创建一个标签,a。如果该行不是文件中的最后一行,则将其附加到模式空间。如果该行不以字符开头>,请执行替换s/\n\([^>]\)/\1/。如果在读取最后一个输入行后替换成功,则分支到 label a。打印到当前模式空间的第一个嵌入换行符。如果模式空间不包含换行符,则开始一个正常的新循环,就像发出了 d 命令一样。否则,删除模式空间中的文本直到第一个换行符,并使用生成的模式空间重新启动循环,而不读取新的输入行。

于 2013-04-07T01:34:09.880 回答
1

您可能对 bioawk 感兴趣,它是 awk 的改编版本,用于处理 fasta 文件

bioawk -c fastx '{ gsub(/\n/,"",seq); print ">"$name; print $seq }' file.fasta

注意: BioAwk基于Brian Kernighan 的 awk,该 awk 记录在Al Aho、Brian Kernighan 和 Peter Weinberger 的“The AWK Programming Language”中(Addison-Wesley,1988,ISBN 0-201-07981-X) 。我不确定这个版本是否与POSIX兼容。

于 2018-10-19T05:01:11.897 回答
1

不要重新发明轮子。如果目标只是删除多行 fasta 文件中的换行符(展开 fasta 文件),请使用任何专门的生物信息学工具,例如seqtk,如下所示:

seqtk seq -l 0 input_file

例子:

# Create the input for testing:

cat > test_unwrap_in.fa <<EOF

>seq1 with blanks
ACGT ACGT ACGT
>seq2 with newlines
ACGT

ACGT

ACGT

>seq3 without blanks or newlines
ACGTACGTACGT

EOF

# Unwrap lines:

seqtk seq -l 0 test_unwrap_in.fa > test_unwrap_out.fa

cat test_unwrap_out.fa

输出:

>seq1 with blanks
ACGT ACGT ACGT
>seq2 with newlines
ACGTACGTACGT
>seq3 without blanks or newlines
ACGTACGTACGT

要安装seqtk,您可以使用例如conda install seqtk.

也可以看看:

seqtk用法:

seqtk seq

Usage:   seqtk seq [options] <in.fq>|<in.fa>

Options: ...
         -l INT    number of residues per line; 0 for 2^32-1 [0]
于 2020-10-08T16:12:55.743 回答
0

另一种变化:-)

awk '!/>/{printf( "%s", $0);next}
     NR>1{printf( "\n")} 
     END {printf"\n"}
     7' YourFile
于 2016-12-21T12:38:41.217 回答
0

使用这个 Perl 单行器,它执行在这种情况和类似情况下所需的所有常见重新格式化:删除序列中的换行符和空格(这也解开序列),但不更改序列标题行。请注意,与其他一些答案不同,这可以正确处理文件中的前导和尾随空格/换行符:

# Create the input for testing:

cat > test_unwrap_in.fa <<EOF

>seq1 with blanks
ACGT ACGT ACGT
>seq2 with newlines
ACGT

ACGT

ACGT

>seq3 without blanks or newlines
ACGTACGTACGT

EOF

# Reformat with Perl:

perl -ne 'chomp; if ( /^>/ ) { print "\n" if $n; print "$_\n"; $n++; } else { s/\s+//g; print; } END { print "\n"; }' test_unwrap_in.fa > test_unwrap_out.fa

输出:

>seq1 with blanks
ACGTACGTACGT
>seq2 with newlines
ACGTACGTACGT
>seq3 without blanks or newlines
ACGTACGTACGT

Perl 单行器使用这些命令行标志:
-e:告诉 Perl 查找内联代码,而不是在文件中。
-n:一次循环输入一行,$_默认情况下将其分配给。

chomp:删除输入行分隔符(\n在 *NIX 上)。
if ( /^>/ ):测试当前行是否为序列标题行。
$n:这个变量在开始时是未定义的(假),在看到第一个序列头后为真,在这种情况下我们打印一个额外的换行符。此换行符位于每个序列的末尾,从第一个序列开始。
END { print "\n"; }:在最后一个序列之后打印最后一个换行符。
s/\s+//g; print;:如果当前行是序列(不是标题),则删除所有空格并在没有终端换行符的情况下打印。

于 2020-09-19T19:54:22.557 回答
0

到目前为止,反响很好。

这是在 Python 中执行此操作的一种有效方法:

def read_fasta(fasta):
    with open(fasta, 'r') as fast:
        headers, sequences = [], []
        for line in fast:
            if line.startswith('>'):
                head = line.replace('>','').strip()
                headers.append(head)
                sequences.append('')
            else :
                seq = line.strip()
                if len(seq) > 0:
                    sequences[-1] += seq
    return (headers, sequences)


def write_fasta(headers, sequences, fasta):
    with open(fasta, 'w') as fast:
        for i in range(len(headers)):
            fast.write('>' + headers[i] + '\n' + sequences[i] + '\n')

您可以使用上述函数从 fasta 文件中检索序列/标题而无需换行,操作它们,然后写回 fasta 文件。

headers, sequences = read_fasta('input.fasta')
new_headers = do_something(headers)
new_sequences = do_something(sequences)
write_fasta(new_headers, new_sequences, 'input.fasta')
于 2020-10-09T23:47:04.190 回答