Switch case 在 Shell 中不起作用

Switch case 在 Shell 中不起作用

我打算用來gdialog取得使用者輸入並將其提供給 shell 中的 switch case。下面是我的程式碼:

#!/bin/sh


which gdialog 2> /dev/null && DIALOG=gdialog || DIALOG=dialog

end () {
    # rm -f $FILE1 $FILE2 $ERROR
    echo "User pressed cancel!"
exit
}

while true
do
    choice=$($DIALOG --title "Messenger" --menu "Command" 8 35 8 \
    "Date" "Get today's date" \
    "Time" "Get today's time")|| end

    # echo $choice

    case "$choice" in
            "Date")

            MSG="Date is requested"
            echo $MSG
            $DIALOG --yesno "$MSG" 7 20 || end          
     ;;
            "Time")
            MSG="Time is requested!"
            $DIALOG --yesno "$MSG" 7 20 || end          
     ;;
    esac
done

問題是 switch case 執行並且控制流到達第一種情況或第二種情況,但MSG變數宣告之後的行不執行。我打算詢問用戶是否想使用 yes/no 繼續gdialog。我在這裡做錯了什麼?

答案1

命令替換被命令的標準輸出替換。對話框使用 stdout 來顯示它的 UI,gdialog afaik 根本不使用它。兩者都使用 stderr 傳回結果。

讓腳本按預期工作的一種方法是在命令替換中將 stdout 與 stderr 交換:

choice=$($DIALOG --title "Messenger" --menu "Command" 8 35 8 \
"Date" "Get today's date" \
"Time" "Get today's time" 3>&2 2>&1 1>&3)|| end

答案2

dialog會將其結果寫入標準錯誤,除非您使用重定向進行一些解決方法,或使用該--stdout選項(因為,像任何curses應用程式一樣,它預設將其顯示寫入標準輸出,並報告標準錯誤)。您不會注意到 with gdialog,因為它將其顯示寫入另一個視窗。

正因為如此,gdialog才會寫沒有什麼到標準輸出,並且$choice將為空。腳本將執行 case 語句,但不符合任何 case。一般來說,case 語句應該有一個預設值,例如,*)以便您可以留言那裡看看發生了什麼事。

不是問題的一部分,但是如何解決這個問題似乎是意料之中的。該腳本引用gdialog,這可能是腳本呼叫zenity原來的gdialog早就沒了)。兩者都沒有--stdout選擇,儘管這可能早於任何一個計劃(參見2000 年以來的變更日誌條目)。您可以在 shell 中透過將檔案描述符交換為標準輸出和錯誤來解決這個問題。自 2000 年底以來,這也已出現在dialog 的範例腳本中,並採用了 Carey Evans(tn5250 開發人員)的建議:

    可以捕獲對話框的輸出,而無需使用
    根本沒有臨時文件,就像我在 tn5250 的“xt5250”腳本中所做的那樣:

        執行3>&1
        XT5250_HOST="`$DIALOG --backtitle "xt5250" --title "連接到主機" \
          --inputbox「輸入要連接的主機的名稱或IP位址:」\
          7 60 2>&1 1>&3`"
        ret=$?
        執行3>&-

    也許你可以考慮使用這樣的東西而不是
    臨時文件。額外的 fd 的詭計變得有點難以實現
    不過,請閱讀。

    >(儘管它們只是示例 - 我應該花多少工作來確保它們的安全?)

    人們_會_剪下並貼上它們。

同意這一點,這有助於停止並解釋腳本。 bash 文件在這裡有幫助,移動文件描述符。這個腳本

(sh myscript.sh 3>&2 2>&1 1>&3) 2>/dev/null

可從右向左讀取為 (a) 移動檔案描述符 1 (標準輸出) 至 3, 2 (標準錯誤)到 1,然後是 3(原來標準輸出) 至 2。

因此,您可以透過將相同系列的變更貼上到檔案描述符來改進腳本:

3>&2 2>&1 1>&3

在分配給choice

choice=$($DIALOG --title "Messenger" --menu "Command" 8 35 8 \
"Date" "Get today's date" \
"Time" "Get today's time" 3>&2 2>&1 1>&3 )|| end

延伸閱讀:

相關內容