【问题标题】:Bash script loop only running onceBash 脚本循环只运行一次
【发布时间】:2023-04-09 03:49:01
【问题描述】:

我正在尝试解析一个输入文件(我的测试文件是 4 行),然后查询一个在线生物数据库。但是,在返回第一个结果后,我的循环似乎停止了。

#!/bin/bash
if [ "$1" = "" ]; then
        echo "No input file to parse given. Give me a BLAST output file"
else
        file=$1
        #Extracts GI from each result and stores it on temp file.
        rm -rf /home/chris/TEMP/tempfile.txt
        awk -F '|' '{printf("%s\n",$2);}' "$file" >> /home/chris/TEMP/tempfile.txt
        #gets the species from each gi.
        input="/home/chris/TEMP/tempfile.txt"
        while read -r i
        do
                echo GI:"$i"
                /home/chris/EntrezDirect/edirect/esearch -db protein -query "$i" | /home/chris/EntrezDirect/edirect/efetch -format gpc | /home/chris/EntrezDirect/edirect/xtract -insd source o
rganism | cut -f2 
        done < "$input"
        rm -rf /home/chris/TEMP/tempfile.txt
fi

例如,我唯一的输出是

GI:751637161

Pseudomonas stutzeri group

而我应该有 4 个结果。任何帮助表示赞赏并提前感谢。

这是示例输入的格式:

TARA042SRF022_1 gi|751637161|ref|WP_041104882.1|    40.4    151 82  2   999 547 1   143 2.8e-21 110.9
TARA042SRF022_2 gi|1057355277|ref|WP_068715547.1|   62.7    263 96  1   915 133 80  342 7.1e-96 358.6
TARA042SRF022_3 gi|950462516|ref|WP_057369049.1|    38.3    47  29  0   184 44  152 198 5.1e+01 36.2
TARA042SRF022_4 gi|918428433|ref|WP_052479609.1|    37.5    48  29  1   525 668 192 238 6.1e+01 37.0

【问题讨论】:

  • 你可以尝试从/dev/null重定向esearch的标准输入;在read -r i 再次运行之前,它似乎正在读取输入文件的其余部分。 esearch -db protein -query "$i" &lt; /dev/null | ....
  • 你可以像这样简化你的 awk:awk -F '|' '{print $2}'.
  • @chepner 是的,这似乎是唯一的选择(除了理论上可以像bash -e -o pipefail script.sh 这样的脚本运行)。
  • @chepner 添加&lt; /dev/null 工作,非常感谢!
  • 请注意,像 Biopython 这样的一些生物信息学库提供了一些方便的接口来解析 Blast 结果。

标签: bash loops bioinformatics


【解决方案1】:

看起来read -r i 在第二次调用时返回非零退出状态,表明没有更多数据可以从输入文件中读取。这通常意味着while 循环内的命令从标准输入读取,并在read 有机会之前消耗文件的其余部分。

这里唯一的候选者是esearch,因为echo 不从标准输入读取,其他命令都是从管道中的前一个命令读取的。重定向esearch 的标准输入,使其不会无意中消耗您的输入数据。

while read -r i
do
    echo GI:"$i"
    /home/chris/EntrezDirect/edirect/esearch -db protein -query "$i" < /dev/null |
      /home/chris/EntrezDirect/edirect/efetch -format gpc |
      /home/chris/EntrezDirect/edirect/xtract -insd source organism |
      cut -f2 
done < "$input"

【讨论】:

    【解决方案2】:

    使用cut 从ASCII 文件中提取列,使用-d 选项表示分隔符,使用-f 指定列。像这样将所有内容都包裹在一个循环中

    $ cat data.txt
    TARA042SRF022_1 gi|751637161|ref|WP_041104882.1|    40.4    151 82  2   999 547 1   143 2.8e-21 110.9
    TARA042SRF022_2 gi|1057355277|ref|WP_068715547.1|   62.7    263 96  1   915 133 80  342 7.1e-96 358.6
    TARA042SRF022_3 gi|950462516|ref|WP_057369049.1|    38.3    47  29  0   184 44  152 198 5.1e+01 36.2
    TARA042SRF022_4 gi|918428433|ref|WP_052479609.1|    37.5    48  29  1   525 668 192 238 6.1e+01 37.0
    
    $ cat t.sh
    #!/bin/bash
    
    for gi in $(cut -d"|" -f 2 data.txt); do
        echo $gi
    done
    
    $ bash t.sh
    751637161
    1057355277
    950462516
    918428433
    

    编辑: 我无法重现该问题,但我觉得它与换行符和/或临时文件的使用有关。我的建议省略了这一点,但没有回答您的实际问题(但我猜是您的问题)

    【讨论】:

    • 它只是切换到一个 for 循环。
    • 您好,感谢您的回复!我从每一行解析 gi 没有问题,这是使用 awk 命令完成的并存储到临时文件中,问题出在之后的 while 循环中。
    • 我无法重现该问题,但我觉得它与换行符和/或临时文件的使用有关。我的建议省略了这一点。
    • @Rolf 我用你的 cut 命令去掉了中间文件,谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-01
    • 2011-11-02
    • 2013-11-28
    相关资源
    最近更新 更多