2014-03-27 50 views
1

我有以下代碼:

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回報的,我總是在$errorlevel得到-1。看起來像$errorlevel根本沒有修改該聲明。

我在哪裏做錯了,我該如何解決這個問題?

PIPESTATUSset -o pipefail等沒有在此情況下使用,否則我將無法告訴用戶是否已經取消了該操作或不(dlg調用GUI)。)

回答

1

如果你不喜歡@devnull的PIPESTATUS解決方案(我會理解的,畢竟它緊密結合您的bash和另一個外殼支持該功能),你也許可以做到這一點是這樣的:

{ 
    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的輸出。它當然不適用於流。

3

我總是得到-1$errorlevel

這是因爲您正在將變量設置爲子外殼。

退出子shell後對變量所做的更改會丟失。您可能要查看${PIPESTATUS[@]}

+0

''PIPESTATUS''或'set -o pipefail'等在這種情況下不可用,否則我將無法判斷用戶是否取消了操作('dlg'調用GUI)。 – user2064000

+3

@ user2064000爲什麼?你想要'wget'的返回碼和'$ {PIPESTATUS [0]}'給你完全的。 'false |真正; echo「$ {PIPESTATUS [*]}」'=>'1 0','true |假;回聲「$ {PIPESTATUS [*]}」'=>'0 1'。 –