我有这个 bash shell-script命令,如果 make 成功,则会导致 date 运行(终止时退出状态为零),反之亦然:
make && date
但现在我想处理它的输出,例如。
make | sed s/a/A/
如果我这样做
make | sed s/a/A/ && date
日期即使 make 失败也会运行。
如果我改为
make && date | sed s/a/A/
sed 处理 date 的输出而不是 make 。
你知道任何解决方案吗?谢谢!
P.S。我试过这些:
(make | sed s/a/A/) && date
当 make 失败时,date 仍在运行。
(make && (date > /dev/null)) | sed s/a/A/
当 make 成功时,date 不会运行。
答案 0 :(得分:10)
如果你确实有一个带有进程替换的shell(bash没有,posix shell不是),而不是
make > >(sed s/a/A/) && date
应该做的伎俩,除了bash它不等待sed(似乎zsh确实如此,但我只尝试过它,没有检查过doc),所以date的输出可以在sed输出的最后一行之前得到。在普通的posix shell中,你可以使用更复杂的构造
((make && date >&3) | sed s/a/A/) 3>&1
在sed处理完所有内容之前,日期可以再次运行,因此它的输出可以再次出现在sed输出的最后一行之前。
如果您希望日期仅在sed处理完所有内容后运行,那么您唯一的机会就是将make状态存储在某处。类似的东西:
(make && touch make-succeeded) | sed s/a/A/
rm make-succeeded 2>/dev/null && date
滥用这个事实,如果该文件不存在,rm(不带-f)将以非零状态退出并使用重定向来消除它的错误消息。正如弗雷德里克所提到的那样,bash确实有一个存放出口状态的地方,所以在bash你可以:
make | sed s/a/A/
[ 0 -eq $PIPESTATUS[0] ] && date
答案 1 :(得分:8)
启用pipefail
子shell中的make
。
(set -o pipefail; make 2>/dev/null | sed s/a/A/) && date
答案 2 :(得分:1)
基本上是这样的;
my_make () {
local rc
make >tmp
rc=$?
sed s/a/A/ tmp
rm tmp
return $rc
}
显然应该以适当的方式处理临时文件;为了集中讨论手头的问题,这是愚蠢的。如果你对文件描述符很聪明,你可能会完全避免使用临时文件,但它是星期五,我需要更多的咖啡。