无法存储$的价值?改变

时间:2014-03-27 09:05:53

标签: bash shell sh wget

我有以下代码:

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似乎没有被该语句修改。

我在哪里做错了,我该如何解决这个问题?

PIPESTATUSset -o pipefail等在这种情况下不可用,否则我将无法判断用户是否已取消操作(dlg调用GUI)。)

2 个答案:

答案 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输出,然后启动seddlg当且仅当wget成功时:

wgetOutput=$(wget ...)
errorlevel=$?
case $errorlevel in
  0)
    echo "$wgetOutput" | sed ... | dlg ...
    ;;
  # add other cases here for handle errors of wget.
esac

但这只适用于wget的有限数量的输出。它当然不会为溪流工作。