我有以下代码:
errorlevel=-1
{ wget "$1" -O "$2" 2>&1; errorlevel=$?; } |\
sed -u 's/^[a-zA-Z\-].*//; s/.* \{1,2\}\([0-9]\{1,3\}\)%.*/\1\n#Downloading... \1%/; s/^20[0-9][0-9].*/#Done./' | \
dlg --progress --percentage=0 --title=Download dialog --text=Starting... --auto-close --auto-kill --button=gtk-cancel
但是,无论wget
返回什么,我总是在-1
中获得$errorlevel
。似乎$errorlevel
似乎没有被该语句修改。
我在哪里做错了,我该如何解决这个问题?
(PIPESTATUS
或set -o pipefail
等在这种情况下不可用,否则我将无法判断用户是否已取消操作(dlg
调用GUI)。)
答案 0 :(得分:3)
我总是在
-1
中获得$errorlevel
。
那是因为你要在子shell中设置变量。
退出子shell时,对变量所做的更改将丢失。
您可能需要查看${PIPESTATUS[@]}
。
答案 1 :(得分:1)
如果您不喜欢@devnull的PIPESTATUS
解决方案(我会理解;毕竟它会与bash
和其他支持该功能的shell紧密相关),您可以做它是这样的:
{
wget "$1" -O "$2" 2>&1
errorlevel=$?
echo "Now I'm using the variable errorlevel:" 1>&2 # redirect to avoid piping this into sed below
case $errorlevel in
143) # segfault?
echo "Whoa!" 1>&2
;;
# ...
esac
} | sed -u 's/^[a-zA-Z\-].*//; s/.* \{1,2\}\([0-9]\{1,3\}\)%.*/\1\n#Downloading... \1%/; s/^20[0-9][0-9].*/#Done./' | \
dlg --progress --percentage=0 --title=Download dialog --text=Starting... --auto-close --auto-kill --button=gtk-cancel
您还可以考虑使用fifo将管道分成两个命令:
mkfifo /tmp/ff
cat /tmp/ff/ | sed ... | dlg ... &
wget ... > /tmp/ff
errorlevel=$?
rm /tmp/ff
通过这种方式,您可能无法捕获sed ... | dlg ...
管道的输出,但这可能对您没有意义。
当然,您可以先退出管道并首先捕获wget
输出,然后启动sed
和dlg
当且仅当wget
成功时:
wgetOutput=$(wget ...)
errorlevel=$?
case $errorlevel in
0)
echo "$wgetOutput" | sed ... | dlg ...
;;
# add other cases here for handle errors of wget.
esac
但这只适用于wget
的有限数量的输出。它当然不会为溪流工作。