2

我正在使用一些遵循以下基本模式的软件运行 bash 脚本。

while read sample; do
    software ${sample} > output.txt
done <samples.txt

对于某些示例,会打印此消息:“站点 Pf3D7_02_v3:274217 与另一个变体重叠,正在跳过...”

此消息不会停止软件运行,但会使结果为假。因此,如果给出消息,我想停止软件并继续 while 循环移动到下一个示例。samples.txt 中有很多示例,这就是我不能手动执行此操作的原因。一种表示消息用于哪个样本的方法也会有所帮助。因为它是我只是得到该消息的许多行,而不知道该消息是针对哪个循环给出的。

有没有可能帮助解决这个问题?

仅供参考,我正在使用的程序称为 bcftools 共识。如果我需要提供更多信息,请告诉我。

编辑:添加了“> output.txt”——意识到我已经把它剥离得太多了

编辑 2:这是使用下面 chepner 建议的完整脚本。抱歉有点辛苦:

mkfifo p
while IFS= read -r sample; do
    bcftools consensus --fasta-ref $HOME/Pf/MSP2_3D7_I_region_ref_noprimer.fasta --sample ${sample} --missing N $EPHEMERAL/bam/Pf_eph/MSP2_I_PfC_Final/Pf_60_public_Pf3D7_02_v3.final.normalised_bcf.vcf.gz --output ${sample}_MSP2_I_consensus_seq.fasta | tee p &
    grep -q -m 1 "The site Pf3D7_02_v3" p && kill $!
done <$HOME/Pf/Pf_git/BF_Mali_samples.txt
rm p
4

2 回答 2

3

我会使用命名管道来 grep 生成的输出。

mkfifo p
while IFS= read -r sample; do
    software "$sample" > p &
    tee < p output.txt | grep -q -m 1 "The site Pf3D7_02_v3:274217" p && kill $!
done < samples.txt
rm p

software将在后台将其输出写入命名管道,但会阻塞直到tee开始读取。tee将从管道中读取并将该数据写入您的输出文件和grep. 如果grep找到匹配项,它将退出并导致kill终止software(如果尚未终止)。

如果您的版本grep不支持该-m选项(它很常见,但非标准),您可以awk改用。

awk '/The site Pf3D7_02:v3:274217/ { exit 1; }' p && kill $!
于 2019-11-13T16:29:35.387 回答
1
while read -u3 sample; do
    software ${sample} | 
    tee output.txt |
    { grep -q -m 1 "The site Pf3D7_02_v3:274217" && cat <&3 }
done 3< samples.txt

输入文件被重定向到文件描述符 3。如果检测到指定的文本,想法是从第 3 个文件描述符中吃掉所有内容。因为我们将输出重定向到一个文件,所以很容易tee output.txt然后检查 grep 的字符串。如果grep成功,那么我们cat <&3从输入中吃掉所有东西,所以接下来read -u3会失败。

或者:

while read sample; do
    if 
        software ${sample} | 
        tee output.txt |
        grep -q -m 1 "The site Pf3D7_02_v3:274217"
    then
        break;
    fi
done < samples.txt

因为管道的退出状态是最后执行的命令,所以我们可以只检查是否grep返回成功,然后中断循环。

于 2019-11-13T17:20:01.080 回答