简单的FASTA txt分离

Simple FASTA txt separation

我有 2 个 Fasta.txt 个文件。我想制作一个 Bash 脚本,在两个文件中循环并检查它是 header 还是序列。 header 以“>”开头。因此,如果它是 header,我希望它只将 header 复制到输出文件中。 另一方面,如果它不是 header,而是序列代码,我也想将它复制到大写的输出中。

到目前为止,我制作了一个如下所示的循环:

#!/bin/bash

for f in seq/*.txt;
do
awk 'BEGIN {RS=">"} {print }' $f;
awk 'BEGIN {RS=">"} {print toupper ()}' $f;
done >> output.txt

我试过 if/else 但 Awk 不愿意工作。

我想要的输出是所有 header 应该在彼此之下,然后在同一个文件中出现所有序列。

我该如何解决这个问题?

如果您放弃 RS 分配并一次只处理一行,可能会更容易。然后您还可以处理 FASTA 文件,其中序列被分成多行,或者 header 行包含空格。

Awk 可以处理多个输入文件,因此不需要单独的 for 循环,在这里或在您最初的尝试中。

您的原始脚本会将所有内容打印到同一个输出文件;所以这个脚本也是这样做的(基本上它只将序列转换为大写,并且单独留下 headers)。

# (Obsoleted by updated requirements)
awk '!/^>/ {[=10=] = toupper([=10=])}1' seq/*.txt >output.txt

这里有一个变体,它像您最初的尝试那样从 header 中删除 >,并将 header 写入单独的文件。 (header 条件以 next 结束,因此如果我们进入脚本的下一行,则此输入行不是 header。)

awk '/^>/ { sub(/>[[:space:]]*/, ""); print >>"headers.txt"; next; }
{[=11=] = toupper([=11=])}1' seq/*.txt >output.txt

如果您希望所有 header 后跟单个输出文件中的所有序列,完成后只需 cat headers.txt output.txt >final.txt。不过,也许您还想规范化,以便每个序列都恰好是一行。这是一个变体:

awk '/^>/ {
  if (n) printf "\n"
  n = 0
  sub(/>[[:space:]]*/, "")
  print >>"headers.txt"
  next
}
{ printf("%s", toupper()); n = 1 }
END { if (n) printf "\n" }' seq/*.txt >sequences.txt

使用 printf 我们可以完全控制写入的内容,因此我们可以禁止在序列的每一行末尾换行。当我们超过序列的末尾时,我们需要打印一个; n 状态变量跟踪这一点,当我们看到新的 header 或文件末尾时,我们添加缺少的换行符。

(将所有内容合并到一个 Awk 脚本中并不难,但是如果您的输入文件很大,那将引入一个严重的问题,因为我们需要将所有序列保存在内存中,直到我们处理完所有 headers,或者对所有输入文件进行两次传递。所以我更愿意保持这种简单和健壮。)

演示:https://ideone.com/uH80nn

顺便说一句,包含文件名的shell变量通常应该是double-quoted;另见 When to wrap quotes around a shell variable?