通过shell中的变量传递命令

时间:2014-05-19 10:51:50

标签: bash shell sh

我的构建脚本中有以下代码:

if [ -z "$1" ]; then
    make -j10 $1 2>&1 | tee log.txt && notify-send -u critical -t 7 "BUILD DONE"
else
    make -j10 $1 2>&1 | tee log.txt | grep -i --color "Error" && notify-send -u critical -t 7 "BUILD DONE"
fi  

我尝试将其优化为:

local GREP=""
[[ ! -z "$1" ]] && GREP="| grep -i --color Error" && echo "Grepping for ERRORS"
make -j10 $1 2>&1 | tee log.txt "$GREP" && notify-send -u critical -t 7 "BUILD DONE"

但是如果$ 1不是空的话,make line中会抛出错误。我只是无法弄清楚如何通过变量传递命令和grep管道。

3 个答案:

答案 0 :(得分:1)

您无法将管道放入command variables

$ foo='| cat'
$ echo bar $foo
bar | cat

链接的文章解释了如何做得很好。

答案 1 :(得分:1)

正如@l0b0's answer中所述,|不会被解释为您所希望的。

如果你想减少重复,你可以这样做:

if [ $(make -j10 "$1" 2>&1 > log.txt) ]; then
    [ "$1" ] && grep -i --color "error" log.txt
    notify-send -u critical -t 7 "BUILD DONE"
fi

测试内部对两个分支都是通用的。您可以将输出间接到tee,而不是使用log.txt以便输出可以输出。如果"$1"不为空,grep表示log.txt中的任何错误。不管怎样,执行notify-send

答案 2 :(得分:1)

正如其他人已经指出的那样,一般来说,你不能期望变量中的命令能够工作。 This is a FAQ.

您可以做的是有条件地执行命令。像这样,例如:

( make -j10 $1 2>&1 && notify-send -u critical -t 7 "BUILD DONE" ) |
tee log.txt |
if [ -z "$1" ]; then
    grep -i --color "Error"
else
    cat
fi

这具有额外的意外好处,notify-send实际上取决于make的退出代码(这可能是您的意图),而不是tee(我希望除非你用完磁盘或其他东西,否则成功。)

(或者如果您想要通知,无论成功状态如何,请将&&更改为; - 我认为这可能更有意义。)

这是cat罕见的有用用途之一(虽然我仍然觉得有必要试图摆脱它!)