这是一个重新发布的帖子生物信息学同样的问题。给出的答案对我不起作用,我想我应该在这里问。
我的目录组织如下:一个主目录,其中有多个项目目录(以“mgp”开头)。每个项目目录内都有多个宏基因组目录(以“mgm”开头并以“.3”结尾)。在每个宏基因组目录中,始终有一个文本 .fna (fasta) 文件。 Fasta 文件由以下结构定义:
>Header1
Sequence1
>Header2
Sequence2
我想要的是一个循环,它将遍历所有这些 fasta 文件,并添加到与项目和元基因组目录相对应的标题代码中。例如,如果项目目录 mgp83581、元基因组子目录 mgm4729322.3 中的 fasta 文件具有以下标头...
>seq1
>seq2
...那么我想将其更改为:
>83581_322_seq1
>83581_322_seq2
基本上,我想添加与项目关联的数字代码,以及与元基因组关联的 7 位代码的最后三位(除了文件名的“.3”部分)。这部分代码没问题。我知道它一次只能处理一个文件。
这是我现在拥有的完整代码。这是行不通的。 (它仅适用于我的两个测试文件之一)
ls mgp*/mgm*.3/*.fna | while read line ; do
header=$(sed -r "s/^mgp([0-9]*)\/mgm[0-9]{4}([0-9]{1,})\.3\/(mgm.*\.fna)/\1_\2/") #this is where I get the code I want from the path
sed -i.bak "s/^>/>${header}_/" $line #this is where I add said code to my file
done
单独来看,部分代码“似乎”有效。如果我写
ls mgp*/mgm*.3/*.fna | while read line ; do
echo $line
done
...然后我就能够恢复我感兴趣的两个测试文件的路径。如果我写:
ls mgp*/mgm*.3/*.fna | while read line ; do
echo $line
header=$(sed -r "s/^mgp([0-9]*)\/mgm[0-9]{4}([0-9]{1,})\.3\/(mgm.*\.fna)/\1_\2/")
echo $header
done
...然后我得到了一些相当奇怪的东西。我得到:
path for file#1
header for file #2
然而,我期望得到:
path for file#1
header for file#1
path for file#2
header for file#2
我看过之前的问题/答案,讨论了 while 循环中变量的行为如何可能有点奇怪,但恐怕我不太了解,无法让事情正常进行。
答案1
您的主要问题是您在运行时sed
没有给它任何输入,这意味着它将读取从包围循环继承的标准输入流,其中包含您传递的文件的名称ls
(所有这些都在第一次迭代中)循环)。另一个问题是您正在使用ls
列出文件(循环文件名比正确读取 的输出更容易、更安全ls
)。此外,考虑到您使用的有点复杂的正则表达式,该代码有点难以阅读。
要循环文件,请使用
for pathname in mgp*/mgm*.3/*.fna; do
# ... use "$pathname" here ...
done
要从子目录名称中获取三位数基因组代码,给定 fasta 文件的路径名$pathname
:
genome=${pathname%.3/*.fna} # trim off tail
genome=${genome#mgp*/mgm????} # trim off head
这将为您提供例如322
in $genome
from mgp83581/mgm4729322.3/blah.fna
in $pathname
。
同理,获取项目编号:
project=${pathname%/mgm*.3/*.fna} # trim off tail
project=${project#mgp} # trim off head
现在$project
会是83581
,而且$genome
也是322
。
>
要在每个 fasta 文件中的行开头的每个后面插入这些内容:
for pathname in mgp*/mgm*.3/*.fna; do
genome=${pathname%.3/*.fna} # trim off tail
genome=${genome#mgp*/mgm????} # trim off head
project=${pathname%/mgm*.3/*.fna} # trim off tail
project=${project#mgp} # trim off head
sed -i .old "s/^>/>${project}_${genome}_/" "$pathname"
done
这还将额外备份带有后缀的旧文件.old
。
注意:在复制您自己的数据。我没有可用的 fasta 文件,也没有测试最终循环。