变量在 while 循环中表现异常

变量在 while 循环中表现异常

这是一个重新发布的帖子生物信息学同样的问题。给出的答案对我不起作用,我想我应该在这里问。

我的目录组织如下:一个主目录,其中有多个项目目录(以“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

这将为您提供例如322in $genomefrom mgp83581/mgm4729322.3/blah.fnain $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 文件,也没有测试最终循环。

相关内容