管道中的条件步骤

时间:2017-01-17 23:21:44

标签: bash pipeline environment

给定一个类似“A | B | C | D | E”的管道,我想让步骤C以步骤B的结果为条件。这样的事情:

A | B | if [ $? -ne 0 ]; then C; else cat; fi | D | E

但这似乎不起作用;无论B的结果如何,C都不会执行。我正在寻找更好的解决方案。

我知道管道的每一步都在自己的子shell中运行。所以我无法将环境变量传递回管道。但是这个管道在Gnu Parallel环境中,许多这样的管道同时运行,并且它们都不知道任何唯一值(它们只处理数据流而不需要知道源,父脚本处理必要的分离)。这意味着使用临时文件也不实用,因为没有任何方法可以使文件名唯一。甚至$$似乎也没有给我一个在每个步骤中都相同的值。

2 个答案:

答案 0 :(得分:4)

您无法使管道成为条件,因为命令是并行运行的。如果在C退出之前未运行B,那么B的输出将通过管道输送到哪里?

您需要将B的输出存储在变量或临时文件中。例如:

out=$(mktemp)
trap 'rm "$out"' EXIT
if A | B > "$out"; then
    C < "$out"
else
    cat "$out"
fi | D | E

答案 1 :(得分:1)

在陈述问题的方式上存在逻辑上的不可能性。

假设像A | B这样的管道。管道的存在是因为我们希望B在A完成之前从A开始读取。因此,当B开始时(这将是你的状况被评估的时候),A还不知道它是否会失败或成功,所以B也不知道。

你可以做的是,有一个回声,作为它的最后一行,某种类型的状态代码。然后B可以从标准输入读取,保存输入(作为临时文件,变量到变量),然后一旦收到最后一行,检查状态然后采取行动。

当然,另一种方法是让A存储自己的输出,然后在完成时,在条件内部使用A(并从管道中消除B)。