シェルでスイッチケースが機能しない

シェルでスイッチケースが機能しない

gdialogユーザー入力を取得して、シェルのケースを切り替えるために使用するつもりです。以下は私のコードです:

#!/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

問題は、スイッチ ケースが実行され、制御フローが最初のケースまたは 2 番目のケースに到達しますが、MSG変数の宣言後の行が実行されないことです。 yes/no を使用して、ユーザーに続行するかどうかを尋ねるつもりですgdialog。ここで何が間違っているのでしょうか?

答え1

コマンド置換は、コマンドの標準出力に置き換えられます。dialog は UI を表示するために stdout を使用しますが、gdialog はそれをまったく使用しないようです。どちらも結果を返すために stderr を使用します。

スクリプトを期待どおりに動作させる 1 つの方法は、コマンド置換で 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は、リダイレクトによる回避策を実行するか、 オプションを使用しない限り、結果を標準エラーに書き込みます(これは、他の curses アプリケーションと同様に、デフォルトで表示を標準出力に書き込み、標準エラーにレポートするためです)。 では、表示が別のウィンドウに書き込まれるため、--stdoutこれに気付かないでしょう。gdialog

このためgdialog何もない標準出力に出力され、$choice空になります。スクリプトはcase文を実行しますが、どのcaseにも一致しません。原則として、case文にはデフォルトが必要です。例:*)メッセージを入れられるようにそこには何が起こっているのか見てみましょう。

質問の一部ではありませんがどうやってこの問題を回避するには、スクリプトが期待されているようです。スクリプトは を参照していますがgdialog、これはおそらくzenityオリジナルgdialog遠い昔)。どちらにもその--stdoutオプションはないが、おそらくどちらのプログラムよりも前からあったものと思われる(2000 年の変更履歴)。シェルでファイル記述子を標準出力とエラーに交換することで、これを回避できます。これは、Carey Evans (tn5250 開発者) の提案を使用して、2000 年後半から dialog のサンプル スクリプトにも含まれています。

    ダイアログからの出力をキャプチャすることは可能ですが、
    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

参考文献:

関連情報