【问题标题】:Terminate Bash script dependent on piped output根据管道输出终止 Bash 脚本
【发布时间】:2015-03-28 23:10:15
【问题描述】:

我编写了以下 shell 脚本:

#!/bin/bash


counter=0

while [ $counter -lt 250 ]; do
        perl Cumulative_Percentage.pl TP53.lst T1_endo.maf >> OutFile
        perl Optimize_Panel.pl TP53.LST T1_endo.maf >> TP53.lst 
        let counter=counter+1
done

而且效果很好。问题是它经常运行比它需要的更多的循环。如果循环应该继续,Perl 脚本 Optimize_Panel.pl 会打印一行,如果循环应该停止则不打印就退出。 如果 Optimize_Panel.pl 退出而不是打印,我希望 while 循环终止...但是如何?

我能想象的一个可能的解决方案是运行

wc TP53.lst

在循环的开始和结束处;首先将它设置为一个变量,然后检查它是否增加了,如果没有附加 TP53.lst,则导致它进入一个过早的 done 语句。我相信这可以工作,但感觉很笨拙,我怀疑有一种更简单的方法来修改 shell 脚本。

我能想到的另一种方法是将 Optimize_Panel.pl 的输出通过管道传输到一个临时文件中,然后以某种方式检查该文件是否为空。

有什么想法吗?

【问题讨论】:

  • 它是否以成功/失败退出代码退出,或者输出是否仅在打印与否方面有所不同?
  • bash 用if [ $? -eq 0 ] 检查最后一个命令的退出状态,然后then let counter=counter+1 else exit ... etc. @rici 是一个很好的方法 - 这样你不必担心触摸脚本。

标签: bash perl shell terminate


【解决方案1】:

您可以在变量中捕获输出,然后如果该变量的长度为零,则退出循环。

while [ $counter -lt 250 ]; do
    perl Cumulative_Percentage.pl TP53.lst T1_endo.maf >> OutFile
    output=$(perl Optimize_Panel.pl TP53.LST T1_endo.maf)
    [ -z "$output" ] && break
    echo "$output" >> TP53.lst 
    let counter=counter+1
done

【讨论】:

    【解决方案2】:

    简单的 hack(以防 perl 脚本不产生有意义的退出状态):

    perl Optimize_Panel.pl TP53.LST T1_endo.maf | grep . >> TP53.lst || break
    

    grep . 匹配任何非空行,因此它是一种删除空行的方法。但这也是一种检测是否有非空行的方法;它会在没有的情况下准确地失败。当然,如果 perl 脚本提供适当的退出状态代码(0 表示成功;非零表示失败)会更好,在这种情况下,您可以省略 | grep . hack。)

    顺便说一句,您可以使用 bash 的算术 for 语句使您的脚本可能更具可读性:

    for ((counter=0; counter < 250; ++counter)); do
        perl Cumulative_Percentage.pl TP53.lst T1_endo.maf >> OutFile
        perl Optimize_Panel.pl TP53.LST T1_endo.maf |
          grep . >> TP53.lst || break;
    done
    

    【讨论】:

    • 非常好 - 这是 shell 编程,所以我不认为这是一个“黑客”......除了“一种简单快速的正确方法”。 ++
    猜你喜欢
    • 2015-11-12
    • 1970-01-01
    • 2012-11-19
    • 1970-01-01
    • 1970-01-01
    • 2016-04-10
    • 2013-04-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多