命令字符串修改乐趣

时间:2013-12-02 11:10:35

标签: bash

考虑以下命令块:

if [[ ${EXTRA_PROCESS} -eq 1 ]]; then
  producer | tee >(calc1 > ${out1}) >(calc2 > ${out2}) | consumer
else
  producer | tee >(calc1 > ${out1}) | consumer
fi

这可以做它应该做的事情。但是,这相当于很多代码重新分区。所以我改变它看起来像这样:

TEE="tee >(calc1 > ${out1})"
if [[ ${EXTRA_PROCESS} -eq 1 ]]; then
  TEE="$TEE >(calc2 > ${out2})"
fi
producer | ${TEE} | consumer

这远远少于代码重复。不幸的是,脚本现在完全坏了。当我运行它时,它会在当前目录中创建三个巨型文件:

blackbox:~ # ls
>
>(calc1
>(calc2
...

(我印象深刻的是,甚至可能首先拥有带有这些名字的文件......删除它们会更有趣!)

有人可以解释

  • 为什么Bash按字面意思处理字符串而不是解释它们?
  • 我如何强迫Bash真正按照我的要求去做?

2 个答案:

答案 0 :(得分:1)

  

为什么Bash在字面上处理字符串而不是解释   它们?

当您将重定向运算符存储在字符串中时,这些运算符往往会失去其特殊含义。这就是您能够拥有>(calc1等文件名的原因。

  

我如何强迫Bash实际按照我的要求行事?

我建议坚持你在第一个代码块中完成它的方式。它似乎可能会重复代码,但不建议使用替代方法(见下文)。


替代(not recommended):

eval "producer | ${TEE} | consumer"

更好的选择是使用函数:

foo1() {
  producer | tee >(calc1 > ${out1}) >(calc2 > ${out2}) | consumer;
}

foo2() {
  producer | tee >(calc1 > ${out1}) | consumer;
}

if [[ ${EXTRA_PROCESS} -eq 1 ]]; then
  foo1
else
  foo2
fi

答案 1 :(得分:0)

我找到了解决方案:

if [[ ${EXTRA_PROCESS} -eq 1 ]]; then
  function Tee()
  {
    tee >(calc1 > ${out1}) >(calc2 > ${out2})
  }
else
  function Tee()
  {
    tee >(calc1 > ${out1})
  }
fi

producer | Tee | consumer

对于实际显示的示例,这是更多的打字。 然而,当您有多个独立的开/关选项时,这样做可以防止稍微不同的管道组合爆炸。

producer | Option1 | Option2 | Option3 | consumer