La caja del interruptor no funciona en Shell

La caja del interruptor no funciona en Shell

Tengo la intención de usarlo gdialogpara tomar la entrada del usuario y alimentarla para cambiar entre mayúsculas y minúsculas en el shell. A continuación se muestra mi código:

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

El problema es que el caso de cambio se ejecuta y el flujo de control llega al primer caso o al segundo caso, pero la línea después de la declaración de MSGla variable no se ejecuta. Tengo la intención de preguntarle al usuario si quiere continuar usando un sí/no gdialog. ¿Qué estoy haciendo mal aquí?

Respuesta1

La sustitución de comandos se reemplaza por la salida estándar del comando. El diálogo usa stdout para mostrar su interfaz de usuario, gdialog afaik no lo usa en absoluto. Ambos usan stderr para devolver el resultado.

Una forma de hacer que su script funcione como espera es intercambiar stdout con stderr en su sustitución de comando:

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

Respuesta2

dialogescribirá su resultado en el error estándar a menos que realice alguna solución con la redirección o use la --stdoutopción (porque, como cualquier aplicación de curses, escribe su visualización en la salida estándar de forma predeterminada e informa sobre el error estándar). No lo notarías con gdialog, ya que escribe su visualización en otra ventana.

Por eso gdialogestaría escribiendonadaa la salida estándar y $choiceestaría vacío. El script ejecutará la declaración del caso, pero no coincidirá con ninguno de los casos. Como regla general, las declaraciones de caso deben tener un valor predeterminado, por ejemplo,*)para que puedas poner un mensajealláy ver lo que está pasando.

No es parte de la pregunta, perocómoParece que se espera que se solucione el problema. El script hace referencia a gdialog, que probablemente sea una llamada de script zenity(eloriginalgdialogeshace mucho). Ninguno de los dos tiene la --stdoutopción, aunque probablemente sea anterior a cualquiera de los programas (verentrada del registro de cambios de 2000). Puede solucionar esto en el shell intercambiando los descriptores de archivo por la salida estándar y el error. Esto también ha estado en los scripts de muestra del diálogo desde finales de 2000, utilizando una sugerencia de Carey Evans (desarrollador de tn5250):

    Es posible capturar el resultado del diálogo, sin usar
    archivos temporales, como lo hice en el script "xt5250" de tn5250:

        ejecutivo 3>&1
        XT5250_HOST="`$DIALOG --backtitle "xt5250" --title "Conectar al host" \
          --inputbox "Ingrese el nombre o la dirección IP del host al que conectarse:" \
          7 60 2>&1 1>&3`"
        retirar=$?
        ejecutivo 3>&-

    Quizás podrías considerar usar algo como esto en lugar de
    archivos temporales. El truco con fd adicionales se vuelve un poco difícil de entender.
    leer, sin embargo.

    > (aunque son ejemplos: ¿cuánto trabajo debo gastar para asegurarlos?)

    La gente los cortará y pegará.

De acuerdo con eso, es útil detenerse y explicar los guiones. La documentación de bash ayuda aquí, conMover descriptores de archivos. este guión

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

se puede leer de derecha a izquierda como (a) mover el descriptor de archivo 1 (salida estándar) a 3, 2 (stderr) a 1 y luego a 3 (originalmentesalida estándar) a 2.

Por lo tanto, podría mejorar su secuencia de comandos pegando la misma serie de cambios en los descriptores de archivos:

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

en la tarea de 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

Otras lecturas:

información relacionada